1 /* -*- C++ -*- |
|
2 * src/lemon/lp_cplex.cc |
|
3 * - Part of LEMON, a generic C++ optimization library |
|
4 * |
|
5 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
6 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
7 * |
|
8 * Permission to use, modify and distribute this software is granted |
|
9 * provided that this copyright notice appears in all copies. For |
|
10 * precise terms see the accompanying LICENSE file. |
|
11 * |
|
12 * This software is provided "AS IS" with no warranty of any kind, |
|
13 * express or implied, and with no claim as to its suitability for any |
|
14 * purpose. |
|
15 * |
|
16 */ |
|
17 #include <iostream> |
|
18 #include<lemon/lp_cplex.h> |
|
19 |
|
20 ///\file |
|
21 ///\brief Implementation of the LEMON-CPLEX lp solver interface. |
|
22 namespace lemon { |
|
23 |
|
24 LpCplex::LpCplex() : LpSolverBase() { |
|
25 env = NULL; |
|
26 lp = NULL; |
|
27 env = CPXopenCPLEXdevelop(&status); |
|
28 // if (Env == NULL) |
|
29 // { |
|
30 // fprintf(stderr,"A CPLEX környezet megnyitása sikertelen.\n"); |
|
31 // CPXgeterrorstring(Env, Status, ErrorMsg); |
|
32 // fprintf(stderr,"%s",ErrorMsg); |
|
33 // goto Terminate; |
|
34 // } |
|
35 |
|
36 // *** A problema létrehozása *** |
|
37 lp = CPXcreateprob(env, &status, "LP problem"); |
|
38 |
|
39 // if (Problem == NULL) |
|
40 // { |
|
41 // fprintf(stderr,"Az LP létrehozása sikertelen"); |
|
42 // goto Terminate; |
|
43 // } |
|
44 |
|
45 } |
|
46 |
|
47 LpCplex::~LpCplex() { |
|
48 status = CPXfreeprob(env,&lp); |
|
49 // if (Status != 0) |
|
50 // { |
|
51 // fprintf(stderr,"A CPLEX feladat törlése sikertelen.\n"); |
|
52 // CPXgeterrorstring(Env, Status, ErrorMsg); |
|
53 // fprintf(stderr,"%s",ErrorMsg); |
|
54 // goto Terminate; |
|
55 // } |
|
56 |
|
57 status = CPXcloseCPLEX(&env); |
|
58 // if (Status != 0) |
|
59 // { |
|
60 // fprintf(stderr,"A CPLEX környezet bezárása sikertelen.\n"); |
|
61 // CPXgeterrorstring(Env, Status, ErrorMsg); |
|
62 // fprintf(stderr,"%s",ErrorMsg); |
|
63 // goto Terminate; |
|
64 // } |
|
65 |
|
66 } |
|
67 |
|
68 LpSolverBase &LpCplex::_newLp() |
|
69 { |
|
70 return *(LpSolverBase*)0; |
|
71 } |
|
72 LpSolverBase &LpCplex::_copyLp() { |
|
73 return *(LpSolverBase*)0; |
|
74 //Ez lesz majd CPXcloneprob (env, lp, &status); |
|
75 } |
|
76 |
|
77 int LpCplex::_addCol() |
|
78 { |
|
79 int i = CPXgetnumcols (env, lp); |
|
80 Value lb[1],ub[1]; |
|
81 lb[0]=-INF;//-CPX_INFBOUND; |
|
82 ub[0]=INF;//CPX_INFBOUND; |
|
83 status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); |
|
84 return i; |
|
85 } |
|
86 |
|
87 int LpCplex::_addRow() |
|
88 { |
|
89 //We want a row that is not constrained |
|
90 char sense[1]; |
|
91 sense[0]='L';//<= constraint |
|
92 Value rhs[1]; |
|
93 rhs[0]=INF; |
|
94 int i = CPXgetnumrows (env, lp); |
|
95 status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); |
|
96 return i; |
|
97 } |
|
98 |
|
99 |
|
100 void LpCplex::_eraseCol(int i) { |
|
101 ///\todo Not implemented yet |
|
102 } |
|
103 |
|
104 void LpCplex::_eraseRow(int i) { |
|
105 ///\todo Not implemented yet |
|
106 } |
|
107 |
|
108 |
|
109 ///\warning Data at index 0 is ignored in the arrays. |
|
110 void LpCplex::_setRowCoeffs(int i, |
|
111 int length, |
|
112 int const * indices, |
|
113 Value const * values ) |
|
114 { |
|
115 int rowlist[length+1]; |
|
116 int* p=rowlist; |
|
117 for (int k=1;k<=length;++k){ |
|
118 rowlist[k]=i; |
|
119 } |
|
120 status = CPXchgcoeflist(env, lp, |
|
121 length, |
|
122 p+1, |
|
123 const_cast<int * >(indices+1), |
|
124 const_cast<Value * >(values+1)); |
|
125 } |
|
126 |
|
127 void LpCplex::_setColCoeffs(int i, |
|
128 int length, |
|
129 int const * indices, |
|
130 Value const * values) |
|
131 { |
|
132 int collist[length+1]; |
|
133 int* p=collist; |
|
134 for (int k=1;k<=length;++k){ |
|
135 collist[k]=i; |
|
136 } |
|
137 status = CPXchgcoeflist(env, lp, |
|
138 length, |
|
139 const_cast<int * >(indices+1), |
|
140 p+1, |
|
141 const_cast<Value * >(values+1)); |
|
142 } |
|
143 |
|
144 void LpCplex::_setCoeff(int row, int col, Value value) |
|
145 { |
|
146 CPXchgcoef (env, lp, row, col, value); |
|
147 } |
|
148 |
|
149 void LpCplex::_setColLowerBound(int i, Value value) |
|
150 { |
|
151 int indices[1]; |
|
152 indices[0]=i; |
|
153 char lu[1]; |
|
154 lu[0]='L'; |
|
155 Value bd[1]; |
|
156 bd[0]=value; |
|
157 status = CPXchgbds (env, lp, 1, indices, lu, bd); |
|
158 |
|
159 } |
|
160 |
|
161 void LpCplex::_setColUpperBound(int i, Value value) |
|
162 { |
|
163 int indices[1]; |
|
164 indices[0]=i; |
|
165 char lu[1]; |
|
166 lu[0]='U'; |
|
167 Value bd[1]; |
|
168 bd[0]=value; |
|
169 status = CPXchgbds (env, lp, 1, indices, lu, bd); |
|
170 } |
|
171 |
|
172 //This will be easier to implement |
|
173 void LpCplex::_setRowBounds(int i, Value lb, Value ub) |
|
174 { |
|
175 //Bad parameter |
|
176 if (lb==INF || ub==-INF) { |
|
177 //FIXME error |
|
178 } |
|
179 |
|
180 int cnt=1; |
|
181 int indices[1]; |
|
182 indices[0]=i; |
|
183 char sense[1]; |
|
184 |
|
185 if (lb==-INF){ |
|
186 sense[0]='L'; |
|
187 CPXchgsense (env, lp, cnt, indices, sense); |
|
188 CPXchgcoef (env, lp, i, -1, ub); |
|
189 |
|
190 } |
|
191 else{ |
|
192 if (ub==INF){ |
|
193 sense[0]='G'; |
|
194 CPXchgsense (env, lp, cnt, indices, sense); |
|
195 CPXchgcoef (env, lp, i, -1, lb); |
|
196 } |
|
197 else{ |
|
198 if (lb == ub){ |
|
199 sense[0]='E'; |
|
200 CPXchgsense (env, lp, cnt, indices, sense); |
|
201 CPXchgcoef (env, lp, i, -1, lb); |
|
202 } |
|
203 else{ |
|
204 sense[0]='R'; |
|
205 CPXchgsense (env, lp, cnt, indices, sense); |
|
206 CPXchgcoef (env, lp, i, -1, lb); |
|
207 CPXchgcoef (env, lp, i, -2, ub-lb); |
|
208 } |
|
209 } |
|
210 } |
|
211 } |
|
212 |
|
213 // void LpCplex::_setRowLowerBound(int i, Value value) |
|
214 // { |
|
215 // //Not implemented, obsolete |
|
216 // } |
|
217 |
|
218 // void LpCplex::_setRowUpperBound(int i, Value value) |
|
219 // { |
|
220 // //Not implemented, obsolete |
|
221 // // //TODO Ezt kell meg megirni |
|
222 // // //type of the problem |
|
223 // // char sense[1]; |
|
224 // // status = CPXgetsense (env, lp, sense, i, i); |
|
225 // // Value rhs[1]; |
|
226 // // status = CPXgetrhs (env, lp, rhs, i, i); |
|
227 |
|
228 // // switch (sense[0]) { |
|
229 // // case 'L'://<= constraint |
|
230 // // break; |
|
231 // // case 'E'://= constraint |
|
232 // // break; |
|
233 // // case 'G'://>= constraint |
|
234 // // break; |
|
235 // // case 'R'://ranged constraint |
|
236 // // break; |
|
237 // // default: ; |
|
238 // // //FIXME error |
|
239 // // } |
|
240 |
|
241 // // status = CPXchgcoef (env, lp, i, -2, value_rng); |
|
242 // } |
|
243 |
|
244 void LpCplex::_setObjCoeff(int i, Value obj_coef) |
|
245 { |
|
246 CPXchgcoef (env, lp, -1, i, obj_coef); |
|
247 } |
|
248 |
|
249 void LpCplex::_clearObj() |
|
250 { |
|
251 for (int i=0;i< CPXgetnumcols (env, lp);++i){ |
|
252 CPXchgcoef (env, lp, -1, i, 0); |
|
253 } |
|
254 |
|
255 } |
|
256 |
|
257 LpCplex::SolveExitStatus LpCplex::_solve() |
|
258 { |
|
259 |
|
260 status = CPXlpopt (env, lp); |
|
261 if (status == 0){ |
|
262 return SOLVED; |
|
263 } |
|
264 else{ |
|
265 return UNSOLVED; |
|
266 } |
|
267 // int i= lpx_simplex(lp); |
|
268 // switch (i) { |
|
269 // case LPX_E_OK: |
|
270 // return SOLVED; |
|
271 // break; |
|
272 // default: |
|
273 // return UNSOLVED; |
|
274 // } |
|
275 } |
|
276 |
|
277 LpCplex::SolutionStatus LpCplex::_getPrimalStatus() |
|
278 { |
|
279 //7.5-os cplex statusai |
|
280 // #define CPX_OPTIMAL 1 |
|
281 // #define CPX_INFEASIBLE 2 |
|
282 // #define CPX_UNBOUNDED 3 |
|
283 // #define CPX_OBJ_LIM 4 |
|
284 // #define CPX_IT_LIM_FEAS 5 |
|
285 // #define CPX_IT_LIM_INFEAS 6 |
|
286 // #define CPX_TIME_LIM_FEAS 7 |
|
287 // #define CPX_TIME_LIM_INFEAS 8 |
|
288 // #define CPX_NUM_BEST_FEAS 9 |
|
289 // #define CPX_NUM_BEST_INFEAS 10 |
|
290 // #define CPX_OPTIMAL_INFEAS 11 |
|
291 // #define CPX_ABORT_FEAS 12 |
|
292 // #define CPX_ABORT_INFEAS 13 |
|
293 // #define CPX_ABORT_DUAL_INFEAS 14 |
|
294 // #define CPX_ABORT_PRIM_INFEAS 15 |
|
295 // #define CPX_ABORT_PRIM_DUAL_INFEAS 16 |
|
296 // #define CPX_ABORT_PRIM_DUAL_FEAS 17 |
|
297 // #define CPX_ABORT_CROSSOVER 18 |
|
298 // #define CPX_INForUNBD 19 |
|
299 // #define CPX_PIVOT 20 |
|
300 |
|
301 // Ezeket hova tegyem: |
|
302 // ??case CPX_ABORT_DUAL_INFEAS |
|
303 // ??case CPX_ABORT_CROSSOVER |
|
304 // ??case CPX_INForUNBD |
|
305 // ??case CPX_PIVOT |
|
306 |
|
307 int stat = CPXgetstat (env, lp); |
|
308 switch (stat) { |
|
309 case 0: |
|
310 return UNDEFINED; //Undefined |
|
311 break; |
|
312 case CPX_OPTIMAL://Optimal |
|
313 return OPTIMAL; |
|
314 break; |
|
315 case CPX_UNBOUNDED://Unbounded |
|
316 return INFINITE; |
|
317 break; |
|
318 case CPX_INFEASIBLE://Infeasible |
|
319 case CPX_IT_LIM_INFEAS: |
|
320 case CPX_TIME_LIM_INFEAS: |
|
321 case CPX_NUM_BEST_INFEAS: |
|
322 case CPX_OPTIMAL_INFEAS: |
|
323 case CPX_ABORT_INFEAS: |
|
324 case CPX_ABORT_PRIM_INFEAS: |
|
325 case CPX_ABORT_PRIM_DUAL_INFEAS: |
|
326 return INFEASIBLE; |
|
327 break; |
|
328 case CPX_OBJ_LIM: |
|
329 case CPX_IT_LIM_FEAS: |
|
330 case CPX_TIME_LIM_FEAS: |
|
331 case CPX_NUM_BEST_FEAS: |
|
332 case CPX_ABORT_FEAS: |
|
333 case CPX_ABORT_PRIM_DUAL_FEAS: |
|
334 return FEASIBLE; |
|
335 break; |
|
336 default: |
|
337 return UNDEFINED; //Everything else comes here |
|
338 //FIXME error |
|
339 } |
|
340 |
|
341 |
|
342 //Nem tudom, hanyas cplex verzio statusai |
|
343 // CPX_STAT_ABORT_DUAL_OBJ_LIM |
|
344 // CPX_STAT_ABORT_IT_LIM |
|
345 // CPX_STAT_ABORT_OBJ_LIM |
|
346 // CPX_STAT_ABORT_PRIM_OBJ_LIM |
|
347 // CPX_STAT_ABORT_TIME_LIM |
|
348 // CPX_STAT_ABORT_USER |
|
349 // CPX_STAT_FEASIBLE_RELAXED |
|
350 // CPX_STAT_INFEASIBLE |
|
351 // CPX_STAT_INForUNBD |
|
352 // CPX_STAT_NUM_BEST |
|
353 // CPX_STAT_OPTIMAL |
|
354 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED |
|
355 // CPX_STAT_OPTIMAL_INFEAS |
|
356 // CPX_STAT_OPTIMAL_RELAXED |
|
357 // CPX_STAT_UNBOUNDED |
|
358 |
|
359 // int stat = CPXgetstat (env, lp); |
|
360 // switch (stat) { |
|
361 // case CPX_STAT_OPTIMAL://Optimal |
|
362 // return OPTIMAL; |
|
363 // break; |
|
364 // case CPX_STAT_INFEASIBLE://Infeasible |
|
365 // return INFEASIBLE; |
|
366 // break; |
|
367 // case CPX_STAT_UNBOUNDED://Unbounded |
|
368 // return INFINITE; |
|
369 // break; |
|
370 // case CPX_STAT_NUM_BEST://Feasible |
|
371 // return FEASIBLE; |
|
372 // break; |
|
373 // default: |
|
374 // return UNDEFINED; //Everything else comes here |
|
375 // //FIXME error |
|
376 // } |
|
377 |
|
378 } |
|
379 |
|
380 LpCplex::Value LpCplex::_getPrimal(int i) |
|
381 { |
|
382 Value x; |
|
383 CPXgetx (env, lp, &x, i, i); |
|
384 return x; |
|
385 } |
|
386 |
|
387 LpCplex::Value LpCplex::_getPrimalValue() |
|
388 { |
|
389 Value objval; |
|
390 //method = CPXgetmethod (env, lp); |
|
391 status = CPXgetobjval (env, lp, &objval); |
|
392 return objval; |
|
393 } |
|
394 |
|
395 |
|
396 |
|
397 |
|
398 void LpCplex::_setMax() |
|
399 { |
|
400 CPXchgobjsen (env, lp, CPX_MAX); |
|
401 } |
|
402 void LpCplex::_setMin() |
|
403 { |
|
404 CPXchgobjsen (env, lp, CPX_MIN); |
|
405 } |
|
406 |
|
407 } //namespace lemon |
|
408 |
|