aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--native/Makefile30
-rw-r--r--native/include/linprog/cplex.h8
-rw-r--r--native/src/linprog/cplex.cpp168
3 files changed, 203 insertions, 3 deletions
diff --git a/native/Makefile b/native/Makefile
index aa8f75c..71a6835 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -45,6 +45,24 @@ ifeq ($(OS),Linux)
45LIBS += -lrt 45LIBS += -lrt
46endif 46endif
47 47
48# #### CPLEX Support ####
49
50# See if we can find a CPLEX installation.
51CPLEX := ${realpath ${shell which cplex}}
52ifneq ($(CPLEX),)
53# Yes, we seem to have something that looks like cplex.
54
55# The CPLEX variable now contains the canonicalized path to the cplex
56# binary. From this, we can extract the include and library paths.
57CPLEX_DIR := ${realpath ${dir $(CPLEX)}/../..}
58
59${info Found CPLEX installation in $(CPLEX_DIR).}
60
61# Add headers, libraries, and definitions.
62INCLUDES += -I$(CPLEX_DIR)/include/
63LIBS += -lilocplex -lcplex -lconcert
64DEFS += -DCONFIG_HAVE_CPLEX
65endif
48 66
49# #### Debug support #### 67# #### Debug support ####
50ifeq ($(DEBUG),y) 68ifeq ($(DEBUG),y)
@@ -61,8 +79,9 @@ endif
61CXXFLAGS = -Wall -Wextra -Werror $(DISABLED_WARNINGS) -fPIC $(INCLUDES) $(DEFS) 79CXXFLAGS = -Wall -Wextra -Werror $(DISABLED_WARNINGS) -fPIC $(INCLUDES) $(DEFS)
62LDFLAGS = $(LIBS) 80LDFLAGS = $(LIBS)
63SWIGFLAGS = -python -c++ -outdir . -includeall -Iinclude 81SWIGFLAGS = -python -c++ -outdir . -includeall -Iinclude
82
64vpath %.cc interface 83vpath %.cc interface
65vpath %.cpp src src/edf src/blocking 84vpath %.cpp src src/edf src/blocking src/linprog
66 85
67# #### Common C++ source files #### 86# #### Common C++ source files ####
68 87
@@ -79,6 +98,11 @@ SYNC_OBJ += rw-phase-fair.o rw-task-fair.o
79 98
80ALL = testmain _sched.so _locking.so _sim.so 99ALL = testmain _sched.so _locking.so _sim.so
81 100
101# Compile LP-based code only if we have a solver.
102ifneq ($(CPLEX),)
103LP_OBJ = cplex.o io.o
104endif
105
82.PHONY: all clean 106.PHONY: all clean
83 107
84all: ${ALL} 108all: ${ALL}
@@ -87,8 +111,8 @@ clean:
87 rm -f interface/*.cc interface/*.o *.py 111 rm -f interface/*.cc interface/*.o *.py
88 rm -f *.o ${ALL} 112 rm -f *.o ${ALL}
89 113
90testmain: testmain.o ${CORE_OBJ} ${SYNC_OBJ} ${EDF_OBJ} ${SCHED_OBJ} 114testmain: testmain.o ${CORE_OBJ} ${SYNC_OBJ} ${EDF_OBJ} ${SCHED_OBJ} ${LP_OBJ}
91 $(CXX) -o $@ $+ $(LDFLAGS) 115 $(CXX) -o $@ $+ $(LDFLAGS)
92 116
93# #### Python libraries #### 117# #### Python libraries ####
94 118
diff --git a/native/include/linprog/cplex.h b/native/include/linprog/cplex.h
new file mode 100644
index 0000000..c68bd24
--- /dev/null
+++ b/native/include/linprog/cplex.h
@@ -0,0 +1,8 @@
1#ifndef LINPROG_CPLEX_H
2#define LINPROG_CPLEX_H
3
4#include "linprog/solver.h"
5
6Solution *cplex_solve(const LinearProgram& lp, unsigned int max_num_vars);
7
8#endif
diff --git a/native/src/linprog/cplex.cpp b/native/src/linprog/cplex.cpp
new file mode 100644
index 0000000..b5565d4
--- /dev/null
+++ b/native/src/linprog/cplex.cpp
@@ -0,0 +1,168 @@
1#define IL_STD // required by CPLEX when using STL classes.
2
3#include <ilcplex/ilocplex.h>
4
5#include "cpu_time.h"
6
7#include "linprog/cplex.h"
8
9class CPLEXSolution : public Solution
10{
11private:
12 IloEnv ilo_env;
13 IloEnv& get_env()
14 {
15 return ilo_env;
16 }
17
18 IloNumArray cplex_values;
19
20 const LinearProgram &linprog;
21
22 bool solved;
23
24 void solve_model(unsigned int max_num_vars,
25 double var_lb, double var_ub);
26
27 IloObjective make_objective(const IloNumVarArray& vars);
28 IloRangeArray make_constraints(const IloNumVarArray& vars);
29
30 IloRange make_constraint(const IloNumVarArray &vars,
31 const LinearExpression *exp, double bound,
32 bool is_exact_bound);
33
34public:
35 CPLEXSolution(const LinearProgram &lp, unsigned int max_num_vars,
36 double var_lb = 0.0, double var_ub = 1.0);
37 ~CPLEXSolution();
38
39 double get_value(unsigned int var) const
40 {
41 return cplex_values[var];
42 }
43
44 bool is_solved() const
45 {
46 return solved;
47 }
48};
49
50CPLEXSolution::CPLEXSolution(const LinearProgram& lp, unsigned int max_num_vars,
51 double var_lb, double var_ub)
52 : ilo_env(),
53 cplex_values(get_env(), max_num_vars),
54 linprog(lp),
55 solved(false)
56{
57 get_env().setNormalizer(IloFalse);
58 get_env().setOut(get_env().getNullStream());
59
60 if (max_num_vars > 0)
61 solve_model(max_num_vars, var_lb, var_ub);
62 else
63 // Trivial case: no variables.
64 solved = true;
65}
66
67
68void CPLEXSolution::solve_model(unsigned int max_num_vars,
69 double var_lb, double var_ub)
70{
71 try
72 {
73 IloNumVarArray cplex_vars = IloNumVarArray(get_env(), max_num_vars,
74 var_lb, var_ub);
75
76 IloObjective objective = make_objective(cplex_vars);
77 IloRangeArray constraints = make_constraints(cplex_vars);
78
79 IloModel model = IloModel(get_env());
80
81 model.add(objective);
82 model.add(constraints);
83
84
85 IloCplex cplex = IloCplex(model);
86
87 cplex.solve();
88
89 cplex.getValues(cplex_vars, cplex_values);
90 solved = true;
91
92 } catch (IloException &ex)
93 {
94 // Improve me: we should export some kind of error info.
95 std::cerr << "CPLEX failed: " << ex << std::endl;
96 solved = false;
97 }
98}
99
100IloObjective CPLEXSolution::make_objective(const IloNumVarArray &vars)
101{
102 const LinearExpression *obj = linprog.get_objective();
103
104 IloObjective goal = IloObjective(get_env(), 0, IloObjective::Maximize);
105 IloNumArray coeffs = IloNumArray(get_env(), vars.getSize());
106
107 assert((int) obj->get_terms().size() <= coeffs.getSize());
108
109 coeffs.add(vars.getSize(), 0);
110
111 // Set coefficient for each variable in the objective function.
112 foreach(obj->get_terms(), term)
113 {
114 double coefficient = term->first;
115 unsigned int var_idx = term->second;
116 coeffs[var_idx] = coefficient;
117 }
118
119 goal.setLinearCoefs(vars, coeffs);
120
121 return goal;
122}
123
124IloRangeArray CPLEXSolution::make_constraints(const IloNumVarArray &vars)
125{
126 IloRangeArray constraints(get_env());
127
128 foreach (linprog.get_equalities(), exp)
129 constraints.add(make_constraint(vars, exp->first, exp->second, true));
130
131 foreach (linprog.get_inequalities(), exp)
132 constraints.add(make_constraint(vars, exp->first, exp->second, false));
133
134 return constraints;
135}
136
137IloRange CPLEXSolution::make_constraint(const IloNumVarArray &vars,
138 const LinearExpression *exp, double bound,
139 bool is_exact_bound)
140{
141 IloRange r = IloRange(get_env(), -IloInfinity, bound);
142
143 if (is_exact_bound)
144 r.setLB(bound);
145
146 foreach (exp->get_terms(), term)
147 r.setLinearCoef(vars[term->second], term->first);
148
149 return r;
150}