|
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 |
|
18 #include"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() {return *(LpSolverBase*)0;} |
|
69 LpSolverBase &LpCplex::_copyLp() {return *(LpSolverBase*)0;} |
|
70 |
|
71 int LpCplex::_addCol() |
|
72 { |
|
73 int i = CPXgetnumcols (env, lp); |
|
74 Value lb[1],ub[1]; |
|
75 lb[0]=-INF;//-CPX_INFBOUND; |
|
76 ub[0]=INF;//CPX_INFBOUND; |
|
77 status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); |
|
78 return i; |
|
79 } |
|
80 |
|
81 int LpCplex::_addRow() |
|
82 { |
|
83 //We want a row that is not constrained |
|
84 char sense[1]; |
|
85 sense[0]='L';//<= constraint |
|
86 Value rhs[1]; |
|
87 rhs[0]=INF; |
|
88 int i = CPXgetnumrows (env, lp); |
|
89 status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); |
|
90 return i; |
|
91 } |
|
92 |
|
93 ///\warning Data at index 0 is ignored in the arrays. |
|
94 void LpCplex::_setRowCoeffs(int i, |
|
95 int length, |
|
96 int const * indices, |
|
97 Value const * values ) |
|
98 { |
|
99 int rowlist[length+1]; |
|
100 int* p=rowlist; |
|
101 for (int k=1;k<=length;++k){ |
|
102 rowlist[k]=i; |
|
103 } |
|
104 status = CPXchgcoeflist(env, lp, |
|
105 length, |
|
106 p+1, |
|
107 const_cast<int * >(indices+1), |
|
108 const_cast<Value * >(values+1)); |
|
109 } |
|
110 |
|
111 void LpCplex::_setColCoeffs(int i, |
|
112 int length, |
|
113 int const * indices, |
|
114 Value const * values) |
|
115 { |
|
116 int collist[length+1]; |
|
117 int* p=collist; |
|
118 for (int k=1;k<=length;++k){ |
|
119 collist[k]=i; |
|
120 } |
|
121 status = CPXchgcoeflist(env, lp, |
|
122 length, |
|
123 const_cast<int * >(indices+1), |
|
124 p+1, |
|
125 const_cast<Value * >(values+1)); |
|
126 } |
|
127 |
|
128 void LpCplex::_setColLowerBound(int i, Value value) |
|
129 { |
|
130 int indices[1]; |
|
131 indices[0]=i; |
|
132 char lu[1]; |
|
133 lu[0]='L'; |
|
134 Value bd[1]; |
|
135 bd[0]=value; |
|
136 status = CPXchgbds (env, lp, 1, indices, lu, bd); |
|
137 |
|
138 } |
|
139 |
|
140 void LpCplex::_setColUpperBound(int i, Value value) |
|
141 { |
|
142 int indices[1]; |
|
143 indices[0]=i; |
|
144 char lu[1]; |
|
145 lu[0]='U'; |
|
146 Value bd[1]; |
|
147 bd[0]=value; |
|
148 status = CPXchgbds (env, lp, 1, indices, lu, bd); |
|
149 } |
|
150 |
|
151 //This will be easier to implement |
|
152 void LpCplex::_setRowBounds(int i, Value lb, Value ub) |
|
153 { |
|
154 //Bad parameter |
|
155 if (lb==INF || ub==-INF) { |
|
156 //FIXME error |
|
157 } |
|
158 |
|
159 int cnt=1; |
|
160 int indices[1]; |
|
161 indices[0]=i; |
|
162 char sense[1]; |
|
163 |
|
164 if (lb==-INF){ |
|
165 sense[0]='L'; |
|
166 CPXchgsense (env, lp, cnt, indices, sense); |
|
167 CPXchgcoef (env, lp, i, -1, ub); |
|
168 } |
|
169 else{ |
|
170 if (ub==INF){ |
|
171 sense[0]='G'; |
|
172 CPXchgsense (env, lp, cnt, indices, sense); |
|
173 CPXchgcoef (env, lp, i, -1, lb); |
|
174 } |
|
175 else{ |
|
176 if (lb == ub){ |
|
177 sense[0]='E'; |
|
178 CPXchgsense (env, lp, cnt, indices, sense); |
|
179 CPXchgcoef (env, lp, i, -1, lb); |
|
180 } |
|
181 else{ |
|
182 sense[0]='R'; |
|
183 CPXchgsense (env, lp, cnt, indices, sense); |
|
184 CPXchgcoef (env, lp, i, -1, lb); |
|
185 CPXchgcoef (env, lp, i, -2, ub-lb); |
|
186 } |
|
187 } |
|
188 } |
|
189 } |
|
190 |
|
191 void LpCplex::_setRowLowerBound(int i, Value value) |
|
192 { |
|
193 //Not implemented, obsolete |
|
194 } |
|
195 |
|
196 void LpCplex::_setRowUpperBound(int i, Value value) |
|
197 { |
|
198 //Not implemented, obsolete |
|
199 // //TODO Ezt kell meg megirni |
|
200 // //type of the problem |
|
201 // char sense[1]; |
|
202 // status = CPXgetsense (env, lp, sense, i, i); |
|
203 // Value rhs[1]; |
|
204 // status = CPXgetrhs (env, lp, rhs, i, i); |
|
205 |
|
206 // switch (sense[0]) { |
|
207 // case 'L'://<= constraint |
|
208 // break; |
|
209 // case 'E'://= constraint |
|
210 // break; |
|
211 // case 'G'://>= constraint |
|
212 // break; |
|
213 // case 'R'://ranged constraint |
|
214 // break; |
|
215 // default: ; |
|
216 // //FIXME error |
|
217 // } |
|
218 |
|
219 // status = CPXchgcoef (env, lp, i, -2, value_rng); |
|
220 } |
|
221 |
|
222 void LpCplex::_setObjCoeff(int i, Value obj_coef) |
|
223 { |
|
224 CPXchgcoef (env, lp, -1, i, obj_coef); |
|
225 } |
|
226 |
|
227 void LpCplex::_clearObj() |
|
228 { |
|
229 for (int i=0;i< CPXgetnumcols (env, lp);++i){ |
|
230 CPXchgcoef (env, lp, -1, i, 0); |
|
231 } |
|
232 |
|
233 } |
|
234 |
|
235 LpCplex::SolveExitStatus LpCplex::_solve() |
|
236 { |
|
237 |
|
238 status = CPXlpopt (env, lp); |
|
239 if (status == 0){ |
|
240 return SOLVED; |
|
241 } |
|
242 else{ |
|
243 return UNSOLVED; |
|
244 } |
|
245 // int i= lpx_simplex(lp); |
|
246 // switch (i) { |
|
247 // case LPX_E_OK: |
|
248 // return SOLVED; |
|
249 // break; |
|
250 // default: |
|
251 // return UNSOLVED; |
|
252 // } |
|
253 } |
|
254 |
|
255 LpCplex::SolutionStatus LpCplex::_getPrimalStatus() |
|
256 { |
|
257 //Unimplemented |
|
258 return OPTIMAL; |
|
259 // int stat= lpx_get_status(lp); |
|
260 // switch (stat) { |
|
261 // case LPX_UNDEF://Undefined (no solve has been run yet) |
|
262 // return UNDEFINED; |
|
263 // break; |
|
264 // case LPX_NOFEAS://There is no feasible solution (primal, I guess) |
|
265 // case LPX_INFEAS://Infeasible |
|
266 // return INFEASIBLE; |
|
267 // break; |
|
268 // case LPX_UNBND://Unbounded |
|
269 // return INFINITE; |
|
270 // break; |
|
271 // case LPX_FEAS://Feasible |
|
272 // return FEASIBLE; |
|
273 // break; |
|
274 // case LPX_OPT://Feasible |
|
275 // return OPTIMAL; |
|
276 // break; |
|
277 // default: |
|
278 // return UNDEFINED; //to avoid gcc warning |
|
279 // //FIXME error |
|
280 // } |
|
281 } |
|
282 |
|
283 LpCplex::Value LpCplex::_getPrimal(int i) |
|
284 { |
|
285 Value x; |
|
286 CPXgetx (env, lp, &x, i, i); |
|
287 return x; |
|
288 } |
|
289 |
|
290 LpCplex::Value LpCplex::_getPrimalValue() |
|
291 { |
|
292 //Unimplemented |
|
293 return 0; |
|
294 } |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 void LpCplex::_setMax() |
|
300 { |
|
301 CPXchgobjsen (env, lp, CPX_MAX); |
|
302 } |
|
303 void LpCplex::_setMin() |
|
304 { |
|
305 CPXchgobjsen (env, lp, CPX_MIN); |
|
306 } |
|
307 |
|
308 } //namespace lemon |
|
309 |