deba@458
|
1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*-
|
deba@458
|
2 |
*
|
deba@458
|
3 |
* This file is a part of LEMON, a generic C++ optimization library.
|
deba@458
|
4 |
*
|
deba@458
|
5 |
* Copyright (C) 2003-2008
|
deba@458
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
deba@458
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
deba@458
|
8 |
*
|
deba@458
|
9 |
* Permission to use, modify and distribute this software is granted
|
deba@458
|
10 |
* provided that this copyright notice appears in all copies. For
|
deba@458
|
11 |
* precise terms see the accompanying LICENSE file.
|
deba@458
|
12 |
*
|
deba@458
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
deba@458
|
14 |
* express or implied, and with no claim as to its suitability for any
|
deba@458
|
15 |
* purpose.
|
deba@458
|
16 |
*
|
deba@458
|
17 |
*/
|
deba@458
|
18 |
|
deba@458
|
19 |
#include <iostream>
|
deba@458
|
20 |
#include <vector>
|
deba@458
|
21 |
#include <lemon/lp_cplex.h>
|
deba@458
|
22 |
|
deba@458
|
23 |
extern "C" {
|
deba@458
|
24 |
#include <ilcplex/cplex.h>
|
deba@458
|
25 |
}
|
deba@458
|
26 |
|
deba@458
|
27 |
|
deba@458
|
28 |
///\file
|
deba@458
|
29 |
///\brief Implementation of the LEMON-CPLEX lp solver interface.
|
deba@458
|
30 |
namespace lemon {
|
deba@458
|
31 |
|
deba@458
|
32 |
LpCplex::LpCplex() {
|
deba@458
|
33 |
// env = CPXopenCPLEXdevelop(&status);
|
deba@458
|
34 |
env = CPXopenCPLEX(&status);
|
deba@458
|
35 |
lp = CPXcreateprob(env, &status, "LP problem");
|
deba@458
|
36 |
}
|
deba@458
|
37 |
|
deba@458
|
38 |
LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
|
deba@458
|
39 |
env = CPXopenCPLEX(&status);
|
deba@458
|
40 |
lp = CPXcloneprob(env, cplex.lp, &status);
|
deba@458
|
41 |
rows = cplex.rows;
|
deba@458
|
42 |
cols = cplex.cols;
|
deba@458
|
43 |
}
|
deba@458
|
44 |
|
deba@458
|
45 |
LpCplex::~LpCplex() {
|
deba@458
|
46 |
CPXfreeprob(env,&lp);
|
deba@458
|
47 |
CPXcloseCPLEX(&env);
|
deba@458
|
48 |
}
|
deba@458
|
49 |
|
deba@458
|
50 |
LpSolverBase* LpCplex::_newLp()
|
deba@458
|
51 |
{
|
deba@458
|
52 |
//The first approach opens a new environment
|
deba@458
|
53 |
return new LpCplex();
|
deba@458
|
54 |
}
|
deba@458
|
55 |
|
deba@458
|
56 |
LpSolverBase* LpCplex::_copyLp() {
|
deba@458
|
57 |
return new LpCplex(*this);
|
deba@458
|
58 |
}
|
deba@458
|
59 |
|
deba@458
|
60 |
int LpCplex::_addCol()
|
deba@458
|
61 |
{
|
deba@458
|
62 |
int i = CPXgetnumcols(env, lp);
|
deba@458
|
63 |
Value lb[1],ub[1];
|
deba@458
|
64 |
lb[0]=-INF;
|
deba@458
|
65 |
ub[0]=INF;
|
deba@458
|
66 |
status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
|
deba@458
|
67 |
return i;
|
deba@458
|
68 |
}
|
deba@458
|
69 |
|
deba@458
|
70 |
|
deba@458
|
71 |
int LpCplex::_addRow()
|
deba@458
|
72 |
{
|
deba@458
|
73 |
//We want a row that is not constrained
|
deba@458
|
74 |
char sense[1];
|
deba@458
|
75 |
sense[0]='L';//<= constraint
|
deba@458
|
76 |
Value rhs[1];
|
deba@458
|
77 |
rhs[0]=INF;
|
deba@458
|
78 |
int i = CPXgetnumrows(env, lp);
|
deba@458
|
79 |
status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
|
deba@458
|
80 |
return i;
|
deba@458
|
81 |
}
|
deba@458
|
82 |
|
deba@458
|
83 |
|
deba@458
|
84 |
void LpCplex::_eraseCol(int i) {
|
deba@458
|
85 |
CPXdelcols(env, lp, i, i);
|
deba@458
|
86 |
}
|
deba@458
|
87 |
|
deba@458
|
88 |
void LpCplex::_eraseRow(int i) {
|
deba@458
|
89 |
CPXdelrows(env, lp, i, i);
|
deba@458
|
90 |
}
|
deba@458
|
91 |
|
deba@458
|
92 |
void LpCplex::_getColName(int col, std::string &name) const
|
deba@458
|
93 |
{
|
deba@458
|
94 |
///\bug Untested
|
deba@458
|
95 |
int storespace;
|
deba@458
|
96 |
CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
|
deba@458
|
97 |
if (storespace == 0) {
|
deba@458
|
98 |
name.clear();
|
deba@458
|
99 |
return;
|
deba@458
|
100 |
}
|
deba@458
|
101 |
|
deba@458
|
102 |
storespace *= -1;
|
deba@458
|
103 |
std::vector<char> buf(storespace);
|
deba@458
|
104 |
char *names[1];
|
deba@458
|
105 |
int dontcare;
|
deba@458
|
106 |
///\bug return code unchecked for error
|
deba@458
|
107 |
CPXgetcolname(env, lp, names, &*buf.begin(), storespace,
|
deba@458
|
108 |
&dontcare, col, col);
|
deba@458
|
109 |
name = names[0];
|
deba@458
|
110 |
}
|
deba@458
|
111 |
|
deba@458
|
112 |
void LpCplex::_setColName(int col, const std::string &name)
|
deba@458
|
113 |
{
|
deba@458
|
114 |
///\bug Untested
|
deba@458
|
115 |
char *names[1];
|
deba@458
|
116 |
names[0] = const_cast<char*>(name.c_str());
|
deba@458
|
117 |
///\bug return code unchecked for error
|
deba@458
|
118 |
CPXchgcolname(env, lp, 1, &col, names);
|
deba@458
|
119 |
}
|
deba@458
|
120 |
|
deba@458
|
121 |
int LpCplex::_colByName(const std::string& name) const
|
deba@458
|
122 |
{
|
deba@458
|
123 |
int index;
|
deba@458
|
124 |
if (CPXgetcolindex(env, lp,
|
deba@458
|
125 |
const_cast<char*>(name.c_str()), &index) == 0) {
|
deba@458
|
126 |
return index;
|
deba@458
|
127 |
}
|
deba@458
|
128 |
return -1;
|
deba@458
|
129 |
}
|
deba@458
|
130 |
|
deba@458
|
131 |
///\warning Data at index 0 is ignored in the arrays.
|
deba@458
|
132 |
void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
|
deba@458
|
133 |
{
|
deba@458
|
134 |
std::vector<int> indices;
|
deba@458
|
135 |
std::vector<int> rowlist;
|
deba@458
|
136 |
std::vector<Value> values;
|
deba@458
|
137 |
|
deba@458
|
138 |
for(ConstRowIterator it=b; it!=e; ++it) {
|
deba@458
|
139 |
indices.push_back(it->first);
|
deba@458
|
140 |
values.push_back(it->second);
|
deba@458
|
141 |
rowlist.push_back(i);
|
deba@458
|
142 |
}
|
deba@458
|
143 |
|
deba@458
|
144 |
status = CPXchgcoeflist(env, lp, values.size(),
|
deba@458
|
145 |
&rowlist[0], &indices[0], &values[0]);
|
deba@458
|
146 |
}
|
deba@458
|
147 |
|
deba@458
|
148 |
void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
|
deba@458
|
149 |
int tmp1, tmp2, tmp3, length;
|
deba@458
|
150 |
CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
|
deba@458
|
151 |
|
deba@458
|
152 |
length = -length;
|
deba@458
|
153 |
std::vector<int> indices(length);
|
deba@458
|
154 |
std::vector<double> values(length);
|
deba@458
|
155 |
|
deba@458
|
156 |
CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
|
deba@458
|
157 |
length, &tmp3, i, i);
|
deba@458
|
158 |
|
deba@458
|
159 |
for (int i = 0; i < length; ++i) {
|
deba@458
|
160 |
*b = std::make_pair(indices[i], values[i]);
|
deba@458
|
161 |
++b;
|
deba@458
|
162 |
}
|
deba@458
|
163 |
|
deba@458
|
164 |
/// \todo implement
|
deba@458
|
165 |
}
|
deba@458
|
166 |
|
deba@458
|
167 |
void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
|
deba@458
|
168 |
{
|
deba@458
|
169 |
std::vector<int> indices;
|
deba@458
|
170 |
std::vector<int> collist;
|
deba@458
|
171 |
std::vector<Value> values;
|
deba@458
|
172 |
|
deba@458
|
173 |
for(ConstColIterator it=b; it!=e; ++it) {
|
deba@458
|
174 |
indices.push_back(it->first);
|
deba@458
|
175 |
values.push_back(it->second);
|
deba@458
|
176 |
collist.push_back(i);
|
deba@458
|
177 |
}
|
deba@458
|
178 |
|
deba@458
|
179 |
status = CPXchgcoeflist(env, lp, values.size(),
|
deba@458
|
180 |
&indices[0], &collist[0], &values[0]);
|
deba@458
|
181 |
}
|
deba@458
|
182 |
|
deba@458
|
183 |
void LpCplex::_getColCoeffs(int i, ColIterator b) const {
|
deba@458
|
184 |
|
deba@458
|
185 |
int tmp1, tmp2, tmp3, length;
|
deba@458
|
186 |
CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
|
deba@458
|
187 |
|
deba@458
|
188 |
length = -length;
|
deba@458
|
189 |
std::vector<int> indices(length);
|
deba@458
|
190 |
std::vector<double> values(length);
|
deba@458
|
191 |
|
deba@458
|
192 |
CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
|
deba@458
|
193 |
length, &tmp3, i, i);
|
deba@458
|
194 |
|
deba@458
|
195 |
for (int i = 0; i < length; ++i) {
|
deba@458
|
196 |
*b = std::make_pair(indices[i], values[i]);
|
deba@458
|
197 |
++b;
|
deba@458
|
198 |
}
|
deba@458
|
199 |
|
deba@458
|
200 |
}
|
deba@458
|
201 |
|
deba@458
|
202 |
void LpCplex::_setCoeff(int row, int col, Value value)
|
deba@458
|
203 |
{
|
deba@458
|
204 |
CPXchgcoef(env, lp, row, col, value);
|
deba@458
|
205 |
}
|
deba@458
|
206 |
|
deba@458
|
207 |
LpCplex::Value LpCplex::_getCoeff(int row, int col) const
|
deba@458
|
208 |
{
|
deba@458
|
209 |
LpCplex::Value value;
|
deba@458
|
210 |
CPXgetcoef(env, lp, row, col, &value);
|
deba@458
|
211 |
return value;
|
deba@458
|
212 |
}
|
deba@458
|
213 |
|
deba@458
|
214 |
void LpCplex::_setColLowerBound(int i, Value value)
|
deba@458
|
215 |
{
|
deba@458
|
216 |
int indices[1];
|
deba@458
|
217 |
indices[0]=i;
|
deba@458
|
218 |
char lu[1];
|
deba@458
|
219 |
lu[0]='L';
|
deba@458
|
220 |
Value bd[1];
|
deba@458
|
221 |
bd[0]=value;
|
deba@458
|
222 |
status = CPXchgbds(env, lp, 1, indices, lu, bd);
|
deba@458
|
223 |
|
deba@458
|
224 |
}
|
deba@458
|
225 |
|
deba@458
|
226 |
LpCplex::Value LpCplex::_getColLowerBound(int i) const
|
deba@458
|
227 |
{
|
deba@458
|
228 |
LpCplex::Value x;
|
deba@458
|
229 |
CPXgetlb (env, lp, &x, i, i);
|
deba@458
|
230 |
if (x <= -CPX_INFBOUND) x = -INF;
|
deba@458
|
231 |
return x;
|
deba@458
|
232 |
}
|
deba@458
|
233 |
|
deba@458
|
234 |
void LpCplex::_setColUpperBound(int i, Value value)
|
deba@458
|
235 |
{
|
deba@458
|
236 |
int indices[1];
|
deba@458
|
237 |
indices[0]=i;
|
deba@458
|
238 |
char lu[1];
|
deba@458
|
239 |
lu[0]='U';
|
deba@458
|
240 |
Value bd[1];
|
deba@458
|
241 |
bd[0]=value;
|
deba@458
|
242 |
status = CPXchgbds(env, lp, 1, indices, lu, bd);
|
deba@458
|
243 |
}
|
deba@458
|
244 |
|
deba@458
|
245 |
LpCplex::Value LpCplex::_getColUpperBound(int i) const
|
deba@458
|
246 |
{
|
deba@458
|
247 |
LpCplex::Value x;
|
deba@458
|
248 |
CPXgetub (env, lp, &x, i, i);
|
deba@458
|
249 |
if (x >= CPX_INFBOUND) x = INF;
|
deba@458
|
250 |
return x;
|
deba@458
|
251 |
}
|
deba@458
|
252 |
|
deba@458
|
253 |
//This will be easier to implement
|
deba@458
|
254 |
void LpCplex::_setRowBounds(int i, Value lb, Value ub)
|
deba@458
|
255 |
{
|
deba@458
|
256 |
//Bad parameter
|
deba@458
|
257 |
if (lb==INF || ub==-INF) {
|
deba@458
|
258 |
//FIXME error
|
deba@458
|
259 |
}
|
deba@458
|
260 |
|
deba@458
|
261 |
int cnt=1;
|
deba@458
|
262 |
int indices[1];
|
deba@458
|
263 |
indices[0]=i;
|
deba@458
|
264 |
char sense[1];
|
deba@458
|
265 |
|
deba@458
|
266 |
if (lb==-INF){
|
deba@458
|
267 |
sense[0]='L';
|
deba@458
|
268 |
CPXchgsense(env, lp, cnt, indices, sense);
|
deba@458
|
269 |
CPXchgcoef(env, lp, i, -1, ub);
|
deba@458
|
270 |
|
deba@458
|
271 |
}
|
deba@458
|
272 |
else{
|
deba@458
|
273 |
if (ub==INF){
|
deba@458
|
274 |
sense[0]='G';
|
deba@458
|
275 |
CPXchgsense(env, lp, cnt, indices, sense);
|
deba@458
|
276 |
CPXchgcoef(env, lp, i, -1, lb);
|
deba@458
|
277 |
}
|
deba@458
|
278 |
else{
|
deba@458
|
279 |
if (lb == ub){
|
deba@458
|
280 |
sense[0]='E';
|
deba@458
|
281 |
CPXchgsense(env, lp, cnt, indices, sense);
|
deba@458
|
282 |
CPXchgcoef(env, lp, i, -1, lb);
|
deba@458
|
283 |
}
|
deba@458
|
284 |
else{
|
deba@458
|
285 |
sense[0]='R';
|
deba@458
|
286 |
CPXchgsense(env, lp, cnt, indices, sense);
|
deba@458
|
287 |
CPXchgcoef(env, lp, i, -1, lb);
|
deba@458
|
288 |
CPXchgcoef(env, lp, i, -2, ub-lb);
|
deba@458
|
289 |
}
|
deba@458
|
290 |
}
|
deba@458
|
291 |
}
|
deba@458
|
292 |
}
|
deba@458
|
293 |
|
deba@458
|
294 |
// void LpCplex::_setRowLowerBound(int i, Value value)
|
deba@458
|
295 |
// {
|
deba@458
|
296 |
// //Not implemented, obsolete
|
deba@458
|
297 |
// }
|
deba@458
|
298 |
|
deba@458
|
299 |
// void LpCplex::_setRowUpperBound(int i, Value value)
|
deba@458
|
300 |
// {
|
deba@458
|
301 |
// //Not implemented, obsolete
|
deba@458
|
302 |
// // //TODO Ezt kell meg megirni
|
deba@458
|
303 |
// // //type of the problem
|
deba@458
|
304 |
// // char sense[1];
|
deba@458
|
305 |
// // status = CPXgetsense(env, lp, sense, i, i);
|
deba@458
|
306 |
// // Value rhs[1];
|
deba@458
|
307 |
// // status = CPXgetrhs(env, lp, rhs, i, i);
|
deba@458
|
308 |
|
deba@458
|
309 |
// // switch (sense[0]) {
|
deba@458
|
310 |
// // case 'L'://<= constraint
|
deba@458
|
311 |
// // break;
|
deba@458
|
312 |
// // case 'E'://= constraint
|
deba@458
|
313 |
// // break;
|
deba@458
|
314 |
// // case 'G'://>= constraint
|
deba@458
|
315 |
// // break;
|
deba@458
|
316 |
// // case 'R'://ranged constraint
|
deba@458
|
317 |
// // break;
|
deba@458
|
318 |
// // default: ;
|
deba@458
|
319 |
// // //FIXME error
|
deba@458
|
320 |
// // }
|
deba@458
|
321 |
|
deba@458
|
322 |
// // status = CPXchgcoef(env, lp, i, -2, value_rng);
|
deba@458
|
323 |
// }
|
deba@458
|
324 |
|
deba@458
|
325 |
void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
|
deba@458
|
326 |
{
|
deba@458
|
327 |
char sense;
|
deba@458
|
328 |
CPXgetsense(env, lp, &sense,i,i);
|
deba@458
|
329 |
lb=-INF;
|
deba@458
|
330 |
ub=INF;
|
deba@458
|
331 |
switch (sense)
|
deba@458
|
332 |
{
|
deba@458
|
333 |
case 'L':
|
deba@458
|
334 |
CPXgetcoef(env, lp, i, -1, &ub);
|
deba@458
|
335 |
break;
|
deba@458
|
336 |
case 'G':
|
deba@458
|
337 |
CPXgetcoef(env, lp, i, -1, &lb);
|
deba@458
|
338 |
break;
|
deba@458
|
339 |
case 'E':
|
deba@458
|
340 |
CPXgetcoef(env, lp, i, -1, &lb);
|
deba@458
|
341 |
ub=lb;
|
deba@458
|
342 |
break;
|
deba@458
|
343 |
case 'R':
|
deba@458
|
344 |
CPXgetcoef(env, lp, i, -1, &lb);
|
deba@458
|
345 |
Value x;
|
deba@458
|
346 |
CPXgetcoef(env, lp, i, -2, &x);
|
deba@458
|
347 |
ub=lb+x;
|
deba@458
|
348 |
break;
|
deba@458
|
349 |
}
|
deba@458
|
350 |
}
|
deba@458
|
351 |
|
deba@458
|
352 |
void LpCplex::_setObjCoeff(int i, Value obj_coef)
|
deba@458
|
353 |
{
|
deba@458
|
354 |
CPXchgcoef(env, lp, -1, i, obj_coef);
|
deba@458
|
355 |
}
|
deba@458
|
356 |
|
deba@458
|
357 |
LpCplex::Value LpCplex::_getObjCoeff(int i) const
|
deba@458
|
358 |
{
|
deba@458
|
359 |
Value x;
|
deba@458
|
360 |
CPXgetcoef(env, lp, -1, i, &x);
|
deba@458
|
361 |
return x;
|
deba@458
|
362 |
}
|
deba@458
|
363 |
|
deba@458
|
364 |
void LpCplex::_clearObj()
|
deba@458
|
365 |
{
|
deba@458
|
366 |
for (int i=0;i< CPXgetnumcols(env, lp);++i){
|
deba@458
|
367 |
CPXchgcoef(env, lp, -1, i, 0);
|
deba@458
|
368 |
}
|
deba@458
|
369 |
|
deba@458
|
370 |
}
|
deba@458
|
371 |
// The routine returns zero unless an error occurred during the
|
deba@458
|
372 |
// optimization. Examples of errors include exhausting available
|
deba@458
|
373 |
// memory (CPXERR_NO_MEMORY) or encountering invalid data in the
|
deba@458
|
374 |
// CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
|
deba@458
|
375 |
// user-specified CPLEX limit, or proving the model infeasible or
|
deba@458
|
376 |
// unbounded, are not considered errors. Note that a zero return
|
deba@458
|
377 |
// value does not necessarily mean that a solution exists. Use query
|
deba@458
|
378 |
// routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
|
deba@458
|
379 |
// further information about the status of the optimization.
|
deba@458
|
380 |
LpCplex::SolveExitStatus LpCplex::_solve()
|
deba@458
|
381 |
{
|
deba@458
|
382 |
//CPX_PARAM_LPMETHOD
|
deba@458
|
383 |
status = CPXlpopt(env, lp);
|
deba@458
|
384 |
//status = CPXprimopt(env, lp);
|
deba@458
|
385 |
#if CPX_VERSION >= 800
|
deba@458
|
386 |
if (status)
|
deba@458
|
387 |
{
|
deba@458
|
388 |
return UNSOLVED;
|
deba@458
|
389 |
}
|
deba@458
|
390 |
else
|
deba@458
|
391 |
{
|
deba@458
|
392 |
switch (CPXgetstat(env, lp))
|
deba@458
|
393 |
{
|
deba@458
|
394 |
case CPX_STAT_OPTIMAL:
|
deba@458
|
395 |
case CPX_STAT_INFEASIBLE:
|
deba@458
|
396 |
case CPX_STAT_UNBOUNDED:
|
deba@458
|
397 |
return SOLVED;
|
deba@458
|
398 |
default:
|
deba@458
|
399 |
return UNSOLVED;
|
deba@458
|
400 |
}
|
deba@458
|
401 |
}
|
deba@458
|
402 |
#else
|
deba@458
|
403 |
if (status == 0){
|
deba@458
|
404 |
//We want to exclude some cases
|
deba@458
|
405 |
switch (CPXgetstat(env, lp)){
|
deba@458
|
406 |
case CPX_OBJ_LIM:
|
deba@458
|
407 |
case CPX_IT_LIM_FEAS:
|
deba@458
|
408 |
case CPX_IT_LIM_INFEAS:
|
deba@458
|
409 |
case CPX_TIME_LIM_FEAS:
|
deba@458
|
410 |
case CPX_TIME_LIM_INFEAS:
|
deba@458
|
411 |
return UNSOLVED;
|
deba@458
|
412 |
default:
|
deba@458
|
413 |
return SOLVED;
|
deba@458
|
414 |
}
|
deba@458
|
415 |
}
|
deba@458
|
416 |
else{
|
deba@458
|
417 |
return UNSOLVED;
|
deba@458
|
418 |
}
|
deba@458
|
419 |
#endif
|
deba@458
|
420 |
}
|
deba@458
|
421 |
|
deba@458
|
422 |
LpCplex::Value LpCplex::_getPrimal(int i) const
|
deba@458
|
423 |
{
|
deba@458
|
424 |
Value x;
|
deba@458
|
425 |
CPXgetx(env, lp, &x, i, i);
|
deba@458
|
426 |
return x;
|
deba@458
|
427 |
}
|
deba@458
|
428 |
|
deba@458
|
429 |
LpCplex::Value LpCplex::_getDual(int i) const
|
deba@458
|
430 |
{
|
deba@458
|
431 |
Value y;
|
deba@458
|
432 |
CPXgetpi(env, lp, &y, i, i);
|
deba@458
|
433 |
return y;
|
deba@458
|
434 |
}
|
deba@458
|
435 |
|
deba@458
|
436 |
LpCplex::Value LpCplex::_getPrimalValue() const
|
deba@458
|
437 |
{
|
deba@458
|
438 |
Value objval;
|
deba@458
|
439 |
//method = CPXgetmethod (env, lp);
|
deba@458
|
440 |
//printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
|
deba@458
|
441 |
CPXgetobjval(env, lp, &objval);
|
deba@458
|
442 |
//printf("Objective value: %g \n",objval);
|
deba@458
|
443 |
return objval;
|
deba@458
|
444 |
}
|
deba@458
|
445 |
bool LpCplex::_isBasicCol(int i) const
|
deba@458
|
446 |
{
|
deba@458
|
447 |
std::vector<int> cstat(CPXgetnumcols(env, lp));
|
deba@458
|
448 |
CPXgetbase(env, lp, &*cstat.begin(), NULL);
|
deba@458
|
449 |
return (cstat[i]==CPX_BASIC);
|
deba@458
|
450 |
}
|
deba@458
|
451 |
|
deba@458
|
452 |
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
|
deba@458
|
453 |
// This table lists the statuses, returned by the CPXgetstat()
|
deba@458
|
454 |
// routine, for solutions to LP problems or mixed integer problems. If
|
deba@458
|
455 |
// no solution exists, the return value is zero.
|
deba@458
|
456 |
|
deba@458
|
457 |
// For Simplex, Barrier
|
deba@458
|
458 |
// 1 CPX_OPTIMAL
|
deba@458
|
459 |
// Optimal solution found
|
deba@458
|
460 |
// 2 CPX_INFEASIBLE
|
deba@458
|
461 |
// Problem infeasible
|
deba@458
|
462 |
// 3 CPX_UNBOUNDED
|
deba@458
|
463 |
// Problem unbounded
|
deba@458
|
464 |
// 4 CPX_OBJ_LIM
|
deba@458
|
465 |
// Objective limit exceeded in Phase II
|
deba@458
|
466 |
// 5 CPX_IT_LIM_FEAS
|
deba@458
|
467 |
// Iteration limit exceeded in Phase II
|
deba@458
|
468 |
// 6 CPX_IT_LIM_INFEAS
|
deba@458
|
469 |
// Iteration limit exceeded in Phase I
|
deba@458
|
470 |
// 7 CPX_TIME_LIM_FEAS
|
deba@458
|
471 |
// Time limit exceeded in Phase II
|
deba@458
|
472 |
// 8 CPX_TIME_LIM_INFEAS
|
deba@458
|
473 |
// Time limit exceeded in Phase I
|
deba@458
|
474 |
// 9 CPX_NUM_BEST_FEAS
|
deba@458
|
475 |
// Problem non-optimal, singularities in Phase II
|
deba@458
|
476 |
// 10 CPX_NUM_BEST_INFEAS
|
deba@458
|
477 |
// Problem non-optimal, singularities in Phase I
|
deba@458
|
478 |
// 11 CPX_OPTIMAL_INFEAS
|
deba@458
|
479 |
// Optimal solution found, unscaled infeasibilities
|
deba@458
|
480 |
// 12 CPX_ABORT_FEAS
|
deba@458
|
481 |
// Aborted in Phase II
|
deba@458
|
482 |
// 13 CPX_ABORT_INFEAS
|
deba@458
|
483 |
// Aborted in Phase I
|
deba@458
|
484 |
// 14 CPX_ABORT_DUAL_INFEAS
|
deba@458
|
485 |
// Aborted in barrier, dual infeasible
|
deba@458
|
486 |
// 15 CPX_ABORT_PRIM_INFEAS
|
deba@458
|
487 |
// Aborted in barrier, primal infeasible
|
deba@458
|
488 |
// 16 CPX_ABORT_PRIM_DUAL_INFEAS
|
deba@458
|
489 |
// Aborted in barrier, primal and dual infeasible
|
deba@458
|
490 |
// 17 CPX_ABORT_PRIM_DUAL_FEAS
|
deba@458
|
491 |
// Aborted in barrier, primal and dual feasible
|
deba@458
|
492 |
// 18 CPX_ABORT_CROSSOVER
|
deba@458
|
493 |
// Aborted in crossover
|
deba@458
|
494 |
// 19 CPX_INForUNBD
|
deba@458
|
495 |
// Infeasible or unbounded
|
deba@458
|
496 |
// 20 CPX_PIVOT
|
deba@458
|
497 |
// User pivot used
|
deba@458
|
498 |
//
|
deba@458
|
499 |
// Ezeket hova tegyem:
|
deba@458
|
500 |
// ??case CPX_ABORT_DUAL_INFEAS
|
deba@458
|
501 |
// ??case CPX_ABORT_CROSSOVER
|
deba@458
|
502 |
// ??case CPX_INForUNBD
|
deba@458
|
503 |
// ??case CPX_PIVOT
|
deba@458
|
504 |
|
deba@458
|
505 |
//Some more interesting stuff:
|
deba@458
|
506 |
|
deba@458
|
507 |
// CPX_PARAM_LPMETHOD 1062 int LPMETHOD
|
deba@458
|
508 |
// 0 Automatic
|
deba@458
|
509 |
// 1 Primal Simplex
|
deba@458
|
510 |
// 2 Dual Simplex
|
deba@458
|
511 |
// 3 Network Simplex
|
deba@458
|
512 |
// 4 Standard Barrier
|
deba@458
|
513 |
// Default: 0
|
deba@458
|
514 |
// Description: Method for linear optimization.
|
deba@458
|
515 |
// Determines which algorithm is used when CPXlpopt() (or "optimize"
|
deba@458
|
516 |
// in the Interactive Optimizer) is called. Currently the behavior of
|
deba@458
|
517 |
// the "Automatic" setting is that CPLEX simply invokes the dual
|
deba@458
|
518 |
// simplex method, but this capability may be expanded in the future
|
deba@458
|
519 |
// so that CPLEX chooses the method based on problem characteristics
|
deba@458
|
520 |
#if CPX_VERSION < 900
|
deba@458
|
521 |
void statusSwitch(CPXENVptr env,int& stat){
|
deba@458
|
522 |
int lpmethod;
|
deba@458
|
523 |
CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
|
deba@458
|
524 |
if (lpmethod==2){
|
deba@458
|
525 |
if (stat==CPX_UNBOUNDED){
|
deba@458
|
526 |
stat=CPX_INFEASIBLE;
|
deba@458
|
527 |
}
|
deba@458
|
528 |
else{
|
deba@458
|
529 |
if (stat==CPX_INFEASIBLE)
|
deba@458
|
530 |
stat=CPX_UNBOUNDED;
|
deba@458
|
531 |
}
|
deba@458
|
532 |
}
|
deba@458
|
533 |
}
|
deba@458
|
534 |
#else
|
deba@458
|
535 |
void statusSwitch(CPXENVptr,int&){}
|
deba@458
|
536 |
#endif
|
deba@458
|
537 |
|
deba@458
|
538 |
LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
|
deba@458
|
539 |
{
|
deba@458
|
540 |
//Unboundedness not treated well: the following is from cplex 9.0 doc
|
deba@458
|
541 |
// About Unboundedness
|
deba@458
|
542 |
|
deba@458
|
543 |
// The treatment of models that are unbounded involves a few
|
deba@458
|
544 |
// subtleties. Specifically, a declaration of unboundedness means that
|
deba@458
|
545 |
// ILOG CPLEX has determined that the model has an unbounded
|
deba@458
|
546 |
// ray. Given any feasible solution x with objective z, a multiple of
|
deba@458
|
547 |
// the unbounded ray can be added to x to give a feasible solution
|
deba@458
|
548 |
// with objective z-1 (or z+1 for maximization models). Thus, if a
|
deba@458
|
549 |
// feasible solution exists, then the optimal objective is
|
deba@458
|
550 |
// unbounded. Note that ILOG CPLEX has not necessarily concluded that
|
deba@458
|
551 |
// a feasible solution exists. Users can call the routine CPXsolninfo
|
deba@458
|
552 |
// to determine whether ILOG CPLEX has also concluded that the model
|
deba@458
|
553 |
// has a feasible solution.
|
deba@458
|
554 |
|
deba@458
|
555 |
int stat = CPXgetstat(env, lp);
|
deba@458
|
556 |
#if CPX_VERSION >= 800
|
deba@458
|
557 |
switch (stat)
|
deba@458
|
558 |
{
|
deba@458
|
559 |
case CPX_STAT_OPTIMAL:
|
deba@458
|
560 |
return OPTIMAL;
|
deba@458
|
561 |
case CPX_STAT_UNBOUNDED:
|
deba@458
|
562 |
return INFINITE;
|
deba@458
|
563 |
case CPX_STAT_INFEASIBLE:
|
deba@458
|
564 |
return INFEASIBLE;
|
deba@458
|
565 |
default:
|
deba@458
|
566 |
return UNDEFINED;
|
deba@458
|
567 |
}
|
deba@458
|
568 |
#else
|
deba@458
|
569 |
statusSwitch(env,stat);
|
deba@458
|
570 |
//CPXgetstat(env, lp);
|
deba@458
|
571 |
//printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
|
deba@458
|
572 |
switch (stat) {
|
deba@458
|
573 |
case 0:
|
deba@458
|
574 |
return UNDEFINED; //Undefined
|
deba@458
|
575 |
case CPX_OPTIMAL://Optimal
|
deba@458
|
576 |
return OPTIMAL;
|
deba@458
|
577 |
case CPX_UNBOUNDED://Unbounded
|
deba@458
|
578 |
return INFEASIBLE;//In case of dual simplex
|
deba@458
|
579 |
//return INFINITE;
|
deba@458
|
580 |
case CPX_INFEASIBLE://Infeasible
|
deba@458
|
581 |
// case CPX_IT_LIM_INFEAS:
|
deba@458
|
582 |
// case CPX_TIME_LIM_INFEAS:
|
deba@458
|
583 |
// case CPX_NUM_BEST_INFEAS:
|
deba@458
|
584 |
// case CPX_OPTIMAL_INFEAS:
|
deba@458
|
585 |
// case CPX_ABORT_INFEAS:
|
deba@458
|
586 |
// case CPX_ABORT_PRIM_INFEAS:
|
deba@458
|
587 |
// case CPX_ABORT_PRIM_DUAL_INFEAS:
|
deba@458
|
588 |
return INFINITE;//In case of dual simplex
|
deba@458
|
589 |
//return INFEASIBLE;
|
deba@458
|
590 |
// case CPX_OBJ_LIM:
|
deba@458
|
591 |
// case CPX_IT_LIM_FEAS:
|
deba@458
|
592 |
// case CPX_TIME_LIM_FEAS:
|
deba@458
|
593 |
// case CPX_NUM_BEST_FEAS:
|
deba@458
|
594 |
// case CPX_ABORT_FEAS:
|
deba@458
|
595 |
// case CPX_ABORT_PRIM_DUAL_FEAS:
|
deba@458
|
596 |
// return FEASIBLE;
|
deba@458
|
597 |
default:
|
deba@458
|
598 |
return UNDEFINED; //Everything else comes here
|
deba@458
|
599 |
//FIXME error
|
deba@458
|
600 |
}
|
deba@458
|
601 |
#endif
|
deba@458
|
602 |
}
|
deba@458
|
603 |
|
deba@458
|
604 |
//9.0-as cplex verzio statusai
|
deba@458
|
605 |
// CPX_STAT_ABORT_DUAL_OBJ_LIM
|
deba@458
|
606 |
// CPX_STAT_ABORT_IT_LIM
|
deba@458
|
607 |
// CPX_STAT_ABORT_OBJ_LIM
|
deba@458
|
608 |
// CPX_STAT_ABORT_PRIM_OBJ_LIM
|
deba@458
|
609 |
// CPX_STAT_ABORT_TIME_LIM
|
deba@458
|
610 |
// CPX_STAT_ABORT_USER
|
deba@458
|
611 |
// CPX_STAT_FEASIBLE_RELAXED
|
deba@458
|
612 |
// CPX_STAT_INFEASIBLE
|
deba@458
|
613 |
// CPX_STAT_INForUNBD
|
deba@458
|
614 |
// CPX_STAT_NUM_BEST
|
deba@458
|
615 |
// CPX_STAT_OPTIMAL
|
deba@458
|
616 |
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
|
deba@458
|
617 |
// CPX_STAT_OPTIMAL_INFEAS
|
deba@458
|
618 |
// CPX_STAT_OPTIMAL_RELAXED
|
deba@458
|
619 |
// CPX_STAT_UNBOUNDED
|
deba@458
|
620 |
|
deba@458
|
621 |
LpCplex::SolutionStatus LpCplex::_getDualStatus() const
|
deba@458
|
622 |
{
|
deba@458
|
623 |
int stat = CPXgetstat(env, lp);
|
deba@458
|
624 |
#if CPX_VERSION >= 800
|
deba@458
|
625 |
switch (stat)
|
deba@458
|
626 |
{
|
deba@458
|
627 |
case CPX_STAT_OPTIMAL:
|
deba@458
|
628 |
return OPTIMAL;
|
deba@458
|
629 |
case CPX_STAT_UNBOUNDED:
|
deba@458
|
630 |
return INFEASIBLE;
|
deba@458
|
631 |
default:
|
deba@458
|
632 |
return UNDEFINED;
|
deba@458
|
633 |
}
|
deba@458
|
634 |
#else
|
deba@458
|
635 |
statusSwitch(env,stat);
|
deba@458
|
636 |
switch (stat) {
|
deba@458
|
637 |
case 0:
|
deba@458
|
638 |
return UNDEFINED; //Undefined
|
deba@458
|
639 |
case CPX_OPTIMAL://Optimal
|
deba@458
|
640 |
return OPTIMAL;
|
deba@458
|
641 |
case CPX_UNBOUNDED:
|
deba@458
|
642 |
return INFEASIBLE;
|
deba@458
|
643 |
default:
|
deba@458
|
644 |
return UNDEFINED; //Everything else comes here
|
deba@458
|
645 |
//FIXME error
|
deba@458
|
646 |
}
|
deba@458
|
647 |
#endif
|
deba@458
|
648 |
}
|
deba@458
|
649 |
|
deba@458
|
650 |
LpCplex::ProblemTypes LpCplex::_getProblemType() const
|
deba@458
|
651 |
{
|
deba@458
|
652 |
int stat = CPXgetstat(env, lp);
|
deba@458
|
653 |
#if CPX_VERSION >= 800
|
deba@458
|
654 |
switch (stat)
|
deba@458
|
655 |
{
|
deba@458
|
656 |
case CPX_STAT_OPTIMAL:
|
deba@458
|
657 |
return PRIMAL_DUAL_FEASIBLE;
|
deba@458
|
658 |
case CPX_STAT_UNBOUNDED:
|
deba@458
|
659 |
return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
|
deba@458
|
660 |
default:
|
deba@458
|
661 |
return UNKNOWN;
|
deba@458
|
662 |
}
|
deba@458
|
663 |
#else
|
deba@458
|
664 |
switch (stat) {
|
deba@458
|
665 |
case CPX_OPTIMAL://Optimal
|
deba@458
|
666 |
return PRIMAL_DUAL_FEASIBLE;
|
deba@458
|
667 |
case CPX_UNBOUNDED:
|
deba@458
|
668 |
return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
|
deba@458
|
669 |
// return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
|
deba@458
|
670 |
// return PRIMAL_DUAL_INFEASIBLE;
|
deba@458
|
671 |
|
deba@458
|
672 |
//Seems to be that this is all we can say for sure
|
deba@458
|
673 |
default:
|
deba@458
|
674 |
//In all other cases
|
deba@458
|
675 |
return UNKNOWN;
|
deba@458
|
676 |
//FIXME error
|
deba@458
|
677 |
}
|
deba@458
|
678 |
#endif
|
deba@458
|
679 |
}
|
deba@458
|
680 |
|
deba@458
|
681 |
void LpCplex::_setMax()
|
deba@458
|
682 |
{
|
deba@458
|
683 |
CPXchgobjsen(env, lp, CPX_MAX);
|
deba@458
|
684 |
}
|
deba@458
|
685 |
void LpCplex::_setMin()
|
deba@458
|
686 |
{
|
deba@458
|
687 |
CPXchgobjsen(env, lp, CPX_MIN);
|
deba@458
|
688 |
}
|
deba@458
|
689 |
|
deba@458
|
690 |
bool LpCplex::_isMax() const
|
deba@458
|
691 |
{
|
deba@458
|
692 |
if (CPXgetobjsen(env, lp)==CPX_MAX)
|
deba@458
|
693 |
return true;
|
deba@458
|
694 |
else
|
deba@458
|
695 |
return false;
|
deba@458
|
696 |
}
|
deba@458
|
697 |
|
deba@458
|
698 |
} //namespace lemon
|
deba@458
|
699 |
|