aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2012-08-13 16:40:19 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-02-12 06:55:15 -0500
commit79818e276e30d037501b4eceaa25b9b2ccffbff6 (patch)
tree5f488f868440f51f4aebb43720e94d62aa605c0d
parent15a7af46ccdbdcc9871113a927104e596638dfc5 (diff)
Implement CPLEX integration via C API
Using the plain, old C API seems to be *much* faster. single: lp_dpcp_bounds::cpu_costs: total=19569.9ms last=93.2767ms average=88.9543ms count=220 lp_dflp_bounds::cpu_costs: total=21537.3ms last=102.459ms average=97.8969ms count=220
-rw-r--r--native/Makefile2
-rw-r--r--native/include/linprog/cplex.h4
-rw-r--r--native/src/linprog/cpx.cpp243
3 files changed, 248 insertions, 1 deletions
diff --git a/native/Makefile b/native/Makefile
index 36cb08f..d722fcd 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -121,7 +121,7 @@ ifneq ($(CPLEX_PATH)$(GLPK_PATH),)
121LP_OBJ = lp_common.o io.o lp_dflp.o lp_dpcp.o 121LP_OBJ = lp_common.o io.o lp_dflp.o lp_dpcp.o
122 122
123ifneq ($(CPLEX_PATH),) 123ifneq ($(CPLEX_PATH),)
124LP_OBJ += cplex.o 124LP_OBJ += cplex.o cpx.o
125endif 125endif
126 126
127ifneq ($(GLPK_PATH),) 127ifneq ($(GLPK_PATH),)
diff --git a/native/include/linprog/cplex.h b/native/include/linprog/cplex.h
index c68bd24..5e7addf 100644
--- a/native/include/linprog/cplex.h
+++ b/native/include/linprog/cplex.h
@@ -3,6 +3,10 @@
3 3
4#include "linprog/solver.h" 4#include "linprog/solver.h"
5 5
6// solve with CPLEX connected via the "Concert Technology" API
6Solution *cplex_solve(const LinearProgram& lp, unsigned int max_num_vars); 7Solution *cplex_solve(const LinearProgram& lp, unsigned int max_num_vars);
7 8
9// solve with CPLEX connected via the plain, old C API
10Solution *cpx_solve(const LinearProgram& lp, unsigned int max_num_vars);
11
8#endif 12#endif
diff --git a/native/src/linprog/cpx.cpp b/native/src/linprog/cpx.cpp
new file mode 100644
index 0000000..f421b0e
--- /dev/null
+++ b/native/src/linprog/cpx.cpp
@@ -0,0 +1,243 @@
1#define IL_STD // required by CPLEX when using STL classes.
2
3#include <assert.h>
4#include <ilcplex/cplex.h>
5
6#include "cpu_time.h"
7
8#include "linprog/cplex.h"
9
10class CPXSolution : public Solution
11{
12private:
13 CPXENVptr env;
14 CPXLPptr lp;
15
16 const LinearProgram &linprog;
17 const unsigned int num_cols;
18 const unsigned int num_rows;
19 unsigned int num_coeffs;
20
21 double *values;
22 bool solved;
23
24 void solve_model(double var_lb, double var_ub);
25
26 bool setup_objective(double lb, double ub);
27 bool add_rows();
28 bool load_coeffs();
29
30public:
31 CPXSolution(const LinearProgram &lp, unsigned int max_num_vars,
32 double var_lb = 0.0, double var_ub = 1.0);
33 ~CPXSolution();
34
35 double get_value(unsigned int var) const
36 {
37 return values[var];
38 }
39
40 bool is_solved() const
41 {
42 return solved;
43 }
44};
45
46CPXSolution::CPXSolution(const LinearProgram& lp, unsigned int max_num_vars,
47 double var_lb, double var_ub)
48 : env(0),
49 lp(0),
50 linprog(lp),
51 num_cols(max_num_vars),
52 num_rows(lp.get_equalities().size() +
53 lp.get_inequalities().size()),
54 num_coeffs(0),
55 values(0),
56 solved(false)
57{
58 if (num_cols > 0)
59 {
60 values = new double[num_cols];
61 solve_model(var_lb, var_ub);
62 } else
63 // Trivial case: no variables.
64 solved = true;
65}
66
67
68void CPXSolution::solve_model(double var_lb, double var_ub)
69{
70 int err;
71
72#if DEBUG_LP_OVERHEADS >= 3
73 static DEFINE_CPU_CLOCK(model_costs);
74 static DEFINE_CPU_CLOCK(solver_costs);
75 static DEFINE_CPU_CLOCK(extract_costs);
76
77 model_costs.start();
78#endif
79
80 env = CPXopenCPLEX(&err);
81
82 if (!env)
83 return;
84
85 lp = CPXcreateprob(env, &err, "blocking");
86
87 if (!lp)
88 return;
89
90
91 if (!setup_objective(var_lb, var_ub) ||
92 !add_rows() ||
93 !load_coeffs())
94 return;
95
96#if DEBUG_LP_OVERHEADS >= 3
97 model_costs.stop();
98 solver_costs.start();
99#endif
100
101 err = CPXlpopt(env, lp);
102
103
104#if DEBUG_LP_OVERHEADS >= 3
105 solver_costs.stop();
106 extract_costs.start();
107#endif
108
109 err = CPXsolution(env, lp, NULL, NULL, values, NULL, NULL, NULL);
110 solved = err == 0;
111
112#if DEBUG_LP_OVERHEADS >= 3
113 extract_costs.stop();
114
115 std::cout << model_costs << std::endl
116 << solver_costs << std::endl
117 << extract_costs << std::endl;
118#endif
119}
120
121CPXSolution::~CPXSolution()
122{
123 int status;
124
125 if (lp) {
126 status = CPXfreeprob(env, &lp);
127 assert(status == 0);
128 }
129
130 if (env) {
131 status = CPXcloseCPLEX(&env);
132 assert(status == 0);
133 }
134
135 delete [] values;
136}
137
138bool CPXSolution::setup_objective(double lb, double ub)
139{
140
141 const LinearExpression *obj = linprog.get_objective();
142 int err;
143
144 double *all = new double[num_cols * 3];
145 double *vals = all;
146 double *lbs = all + num_cols;
147 double *ubs = all + 2 * num_cols;
148
149 assert(obj->get_terms().size() == num_cols);
150
151 foreach(obj->get_terms(), term)
152 vals[term->second] = term->first;
153
154 for (unsigned int i = 0; i < num_cols; i++)
155 {
156 lbs[i] = lb;
157 ubs[i] = ub;
158 }
159
160 CPXchgobjsen(env, lp, CPX_MAX);
161 err = CPXnewcols(env, lp, num_cols, vals, lbs, ubs, NULL, NULL);
162
163 delete [] all;
164
165 return err == 0;
166}
167
168bool CPXSolution::add_rows()
169{
170 double *bounds = new double[num_rows];
171 char *senses = new char[num_rows];
172 int err;
173
174 unsigned int r = 0;
175
176 foreach(linprog.get_equalities(), equ)
177 {
178 bounds[r] = equ->second;
179 senses[r] = 'E'; // equality constraint
180
181 num_coeffs += equ->first->get_terms().size();
182 r++;
183 }
184
185 foreach(linprog.get_inequalities(), inequ)
186 {
187 bounds[r] = inequ->second;
188 senses[r] = 'L'; // less-than-or-equal constraint
189
190 num_coeffs += inequ->first->get_terms().size();
191 r++;
192 }
193
194
195 err = CPXnewrows(env, lp, num_rows, bounds, senses, NULL, NULL);
196
197 delete [] bounds;
198 delete [] senses;
199
200 return err == 0;
201}
202
203bool CPXSolution::load_coeffs()
204{
205 unsigned int r = 0;
206 int err;
207
208 foreach(linprog.get_equalities(), equ)
209 {
210 foreach(equ->first->get_terms(), term)
211 {
212 err = CPXchgcoef(env, lp, r, term->second, term->first);
213 if (err != 0)
214 return false;
215 }
216 r++;
217 }
218
219 foreach(linprog.get_inequalities(), inequ)
220 {
221 foreach(inequ->first->get_terms(), term)
222 {
223 err = CPXchgcoef(env, lp, r, term->second, term->first);
224 if (err != 0)
225 return false;
226 }
227 r++;
228 }
229
230 return true;
231}
232
233Solution *cpx_solve(const LinearProgram& lp, unsigned int max_num_vars)
234{
235 CPXSolution *sol = new CPXSolution(lp, max_num_vars);
236 if (sol->is_solved())
237 return sol;
238 else
239 {
240 delete sol;
241 return NULL;
242 }
243}