Changeset 459:ed54c0d13df0 in lemon-1.2 for lemon/lp_cplex.cc
- Timestamp:
- 12/02/08 22:48:28 (15 years ago)
- Branch:
- default
- Children:
- 460:76ec7bd57026, 502:17cabb114d52
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lemon/lp_cplex.cc
r458 r459 19 19 #include <iostream> 20 20 #include <vector> 21 #include <cstring> 22 21 23 #include <lemon/lp_cplex.h> 22 24 … … 30 32 namespace lemon { 31 33 32 LpCplex::LpCplex() { 33 // env = CPXopenCPLEXdevelop(&status); 34 env = CPXopenCPLEX(&status); 35 lp = CPXcreateprob(env, &status, "LP problem"); 36 } 37 38 LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() { 39 env = CPXopenCPLEX(&status); 40 lp = CPXcloneprob(env, cplex.lp, &status); 34 CplexEnv::LicenseError::LicenseError(int status) { 35 if (!CPXgeterrorstring(0, status, _message)) { 36 std::strcpy(_message, "Cplex unknown error"); 37 } 38 } 39 40 CplexEnv::CplexEnv() { 41 int status; 42 _cnt = new int; 43 _env = CPXopenCPLEX(&status); 44 if (_env == 0) { 45 delete _cnt; 46 _cnt = 0; 47 throw LicenseError(status); 48 } 49 } 50 51 CplexEnv::CplexEnv(const CplexEnv& other) { 52 _env = other._env; 53 _cnt = other._cnt; 54 ++(*_cnt); 55 } 56 57 CplexEnv& CplexEnv::operator=(const CplexEnv& other) { 58 _env = other._env; 59 _cnt = other._cnt; 60 ++(*_cnt); 61 return *this; 62 } 63 64 CplexEnv::~CplexEnv() { 65 --(*_cnt); 66 if (*_cnt == 0) { 67 delete _cnt; 68 CPXcloseCPLEX(&_env); 69 } 70 } 71 72 CplexBase::CplexBase() : LpBase() { 73 int status; 74 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); 75 } 76 77 CplexBase::CplexBase(const CplexEnv& env) 78 : LpBase(), _env(env) { 79 int status; 80 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); 81 } 82 83 CplexBase::CplexBase(const CplexBase& cplex) 84 : LpBase() { 85 int status; 86 _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status); 41 87 rows = cplex.rows; 42 88 cols = cplex.cols; 43 89 } 44 90 45 LpCplex::~LpCplex() { 46 CPXfreeprob(env,&lp); 47 CPXcloseCPLEX(&env); 48 } 49 50 LpSolverBase* LpCplex::_newLp() 51 { 52 //The first approach opens a new environment 53 return new LpCplex(); 54 } 55 56 LpSolverBase* LpCplex::_copyLp() { 57 return new LpCplex(*this); 58 } 59 60 int LpCplex::_addCol() 61 { 62 int i = CPXgetnumcols(env, lp); 63 Value lb[1],ub[1]; 64 lb[0]=-INF; 65 ub[0]=INF; 66 status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL); 91 CplexBase::~CplexBase() { 92 CPXfreeprob(cplexEnv(),&_prob); 93 } 94 95 int CplexBase::_addCol() { 96 int i = CPXgetnumcols(cplexEnv(), _prob); 97 double lb = -INF, ub = INF; 98 CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0); 67 99 return i; 68 100 } 69 101 70 102 71 int LpCplex::_addRow() 72 { 73 //We want a row that is not constrained 74 char sense[1]; 75 sense[0]='L';//<= constraint 76 Value rhs[1]; 77 rhs[0]=INF; 78 int i = CPXgetnumrows(env, lp); 79 status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL); 103 int CplexBase::_addRow() { 104 int i = CPXgetnumrows(cplexEnv(), _prob); 105 const double ub = INF; 106 const char s = 'L'; 107 CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0); 80 108 return i; 81 109 } 82 110 83 111 84 void LpCplex::_eraseCol(int i) { 85 CPXdelcols(env, lp, i, i); 86 } 87 88 void LpCplex::_eraseRow(int i) { 89 CPXdelrows(env, lp, i, i); 90 } 91 92 void LpCplex::_getColName(int col, std::string &name) const 93 { 94 ///\bug Untested 95 int storespace; 96 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col); 97 if (storespace == 0) { 112 void CplexBase::_eraseCol(int i) { 113 CPXdelcols(cplexEnv(), _prob, i, i); 114 } 115 116 void CplexBase::_eraseRow(int i) { 117 CPXdelrows(cplexEnv(), _prob, i, i); 118 } 119 120 void CplexBase::_eraseColId(int i) { 121 cols.eraseIndex(i); 122 cols.shiftIndices(i); 123 } 124 void CplexBase::_eraseRowId(int i) { 125 rows.eraseIndex(i); 126 rows.shiftIndices(i); 127 } 128 129 void CplexBase::_getColName(int col, std::string &name) const { 130 int size; 131 CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col); 132 if (size == 0) { 98 133 name.clear(); 99 134 return; 100 135 } 101 136 102 storespace *= -1; 103 std::vector<char> buf(storespace); 104 char *names[1]; 105 int dontcare; 106 ///\bug return code unchecked for error 107 CPXgetcolname(env, lp, names, &*buf.begin(), storespace, 108 &dontcare, col, col); 109 name = names[0]; 110 } 111 112 void LpCplex::_setColName(int col, const std::string &name) 113 { 114 ///\bug Untested 115 char *names[1]; 116 names[0] = const_cast<char*>(name.c_str()); 117 ///\bug return code unchecked for error 118 CPXchgcolname(env, lp, 1, &col, names); 119 } 120 121 int LpCplex::_colByName(const std::string& name) const 122 { 137 size *= -1; 138 std::vector<char> buf(size); 139 char *cname; 140 int tmp; 141 CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size, 142 &tmp, col, col); 143 name = cname; 144 } 145 146 void CplexBase::_setColName(int col, const std::string &name) { 147 char *cname; 148 cname = const_cast<char*>(name.c_str()); 149 CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname); 150 } 151 152 int CplexBase::_colByName(const std::string& name) const { 123 153 int index; 124 if (CPXgetcolindex( env, lp,154 if (CPXgetcolindex(cplexEnv(), _prob, 125 155 const_cast<char*>(name.c_str()), &index) == 0) { 126 156 return index; … … 129 159 } 130 160 131 ///\warning Data at index 0 is ignored in the arrays. 132 void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) 161 void CplexBase::_getRowName(int row, std::string &name) const { 162 int size; 163 CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row); 164 if (size == 0) { 165 name.clear(); 166 return; 167 } 168 169 size *= -1; 170 std::vector<char> buf(size); 171 char *cname; 172 int tmp; 173 CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size, 174 &tmp, row, row); 175 name = cname; 176 } 177 178 void CplexBase::_setRowName(int row, const std::string &name) { 179 char *cname; 180 cname = const_cast<char*>(name.c_str()); 181 CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname); 182 } 183 184 int CplexBase::_rowByName(const std::string& name) const { 185 int index; 186 if (CPXgetrowindex(cplexEnv(), _prob, 187 const_cast<char*>(name.c_str()), &index) == 0) { 188 return index; 189 } 190 return -1; 191 } 192 193 void CplexBase::_setRowCoeffs(int i, ExprIterator b, 194 ExprIterator e) 133 195 { 134 196 std::vector<int> indices; … … 136 198 std::vector<Value> values; 137 199 138 for( ConstRowIterator it=b; it!=e; ++it) {200 for(ExprIterator it=b; it!=e; ++it) { 139 201 indices.push_back(it->first); 140 202 values.push_back(it->second); … … 142 204 } 143 205 144 status = CPXchgcoeflist(env, lp, values.size(),145 &rowlist[0], &indices[0], &values[0]);146 } 147 148 void LpCplex::_getRowCoeffs(int i, RowIterator b) const {206 CPXchgcoeflist(cplexEnv(), _prob, values.size(), 207 &rowlist.front(), &indices.front(), &values.front()); 208 } 209 210 void CplexBase::_getRowCoeffs(int i, InsertIterator b) const { 149 211 int tmp1, tmp2, tmp3, length; 150 CPXgetrows( env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);212 CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i); 151 213 152 214 length = -length; … … 154 216 std::vector<double> values(length); 155 217 156 CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 218 CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 219 &indices.front(), &values.front(), 157 220 length, &tmp3, i, i); 158 221 … … 161 224 ++b; 162 225 } 163 164 /// \todo implement 165 } 166 167 void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) 168 { 226 } 227 228 void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) { 169 229 std::vector<int> indices; 170 230 std::vector<int> collist; 171 231 std::vector<Value> values; 172 232 173 for( ConstColIterator it=b; it!=e; ++it) {233 for(ExprIterator it=b; it!=e; ++it) { 174 234 indices.push_back(it->first); 175 235 values.push_back(it->second); … … 177 237 } 178 238 179 status = CPXchgcoeflist(env, lp, values.size(),180 &indices[0], &collist[0], &values[0]);181 } 182 183 void LpCplex::_getColCoeffs(int i, ColIterator b) const {239 CPXchgcoeflist(cplexEnv(), _prob, values.size(), 240 &indices.front(), &collist.front(), &values.front()); 241 } 242 243 void CplexBase::_getColCoeffs(int i, InsertIterator b) const { 184 244 185 245 int tmp1, tmp2, tmp3, length; 186 CPXgetcols( env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);246 CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i); 187 247 188 248 length = -length; … … 190 250 std::vector<double> values(length); 191 251 192 CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 252 CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 253 &indices.front(), &values.front(), 193 254 length, &tmp3, i, i); 194 255 … … 200 261 } 201 262 202 void LpCplex::_setCoeff(int row, int col, Value value) 263 void CplexBase::_setCoeff(int row, int col, Value value) { 264 CPXchgcoef(cplexEnv(), _prob, row, col, value); 265 } 266 267 CplexBase::Value CplexBase::_getCoeff(int row, int col) const { 268 CplexBase::Value value; 269 CPXgetcoef(cplexEnv(), _prob, row, col, &value); 270 return value; 271 } 272 273 void CplexBase::_setColLowerBound(int i, Value value) { 274 const char s = 'L'; 275 CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value); 276 } 277 278 CplexBase::Value CplexBase::_getColLowerBound(int i) const { 279 CplexBase::Value res; 280 CPXgetlb(cplexEnv(), _prob, &res, i, i); 281 return res <= -CPX_INFBOUND ? -INF : res; 282 } 283 284 void CplexBase::_setColUpperBound(int i, Value value) 203 285 { 204 CPXchgcoef(env, lp, row, col, value); 205 } 206 207 LpCplex::Value LpCplex::_getCoeff(int row, int col) const 286 const char s = 'U'; 287 CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value); 288 } 289 290 CplexBase::Value CplexBase::_getColUpperBound(int i) const { 291 CplexBase::Value res; 292 CPXgetub(cplexEnv(), _prob, &res, i, i); 293 return res >= CPX_INFBOUND ? INF : res; 294 } 295 296 CplexBase::Value CplexBase::_getRowLowerBound(int i) const { 297 char s; 298 CPXgetsense(cplexEnv(), _prob, &s, i, i); 299 CplexBase::Value res; 300 301 switch (s) { 302 case 'G': 303 case 'R': 304 case 'E': 305 CPXgetrhs(cplexEnv(), _prob, &res, i, i); 306 return res <= -CPX_INFBOUND ? -INF : res; 307 default: 308 return -INF; 309 } 310 } 311 312 CplexBase::Value CplexBase::_getRowUpperBound(int i) const { 313 char s; 314 CPXgetsense(cplexEnv(), _prob, &s, i, i); 315 CplexBase::Value res; 316 317 switch (s) { 318 case 'L': 319 case 'E': 320 CPXgetrhs(cplexEnv(), _prob, &res, i, i); 321 return res >= CPX_INFBOUND ? INF : res; 322 case 'R': 323 CPXgetrhs(cplexEnv(), _prob, &res, i, i); 324 { 325 double rng; 326 CPXgetrngval(cplexEnv(), _prob, &rng, i, i); 327 res += rng; 328 } 329 return res >= CPX_INFBOUND ? INF : res; 330 default: 331 return INF; 332 } 333 } 334 335 //This is easier to implement 336 void CplexBase::_set_row_bounds(int i, Value lb, Value ub) { 337 if (lb == -INF) { 338 const char s = 'L'; 339 CPXchgsense(cplexEnv(), _prob, 1, &i, &s); 340 CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub); 341 } else if (ub == INF) { 342 const char s = 'G'; 343 CPXchgsense(cplexEnv(), _prob, 1, &i, &s); 344 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb); 345 } else if (lb == ub){ 346 const char s = 'E'; 347 CPXchgsense(cplexEnv(), _prob, 1, &i, &s); 348 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb); 349 } else { 350 const char s = 'R'; 351 CPXchgsense(cplexEnv(), _prob, 1, &i, &s); 352 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb); 353 double len = ub - lb; 354 CPXchgrngval(cplexEnv(), _prob, 1, &i, &len); 355 } 356 } 357 358 void CplexBase::_setRowLowerBound(int i, Value lb) 208 359 { 209 LpCplex::Value value; 210 CPXgetcoef(env, lp, row, col, &value); 211 return value; 212 } 213 214 void LpCplex::_setColLowerBound(int i, Value value) 360 LEMON_ASSERT(lb != INF, "Invalid bound"); 361 _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i)); 362 } 363 364 void CplexBase::_setRowUpperBound(int i, Value ub) 215 365 { 216 int indices[1]; 217 indices[0]=i; 218 char lu[1]; 219 lu[0]='L'; 220 Value bd[1]; 221 bd[0]=value; 222 status = CPXchgbds(env, lp, 1, indices, lu, bd); 223 224 } 225 226 LpCplex::Value LpCplex::_getColLowerBound(int i) const 366 367 LEMON_ASSERT(ub != -INF, "Invalid bound"); 368 _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub); 369 } 370 371 void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e) 227 372 { 228 LpCplex::Value x; 229 CPXgetlb (env, lp, &x, i, i); 230 if (x <= -CPX_INFBOUND) x = -INF; 231 return x; 232 } 233 234 void LpCplex::_setColUpperBound(int i, Value value) 373 std::vector<int> indices; 374 std::vector<Value> values; 375 for(ExprIterator it=b; it!=e; ++it) { 376 indices.push_back(it->first); 377 values.push_back(it->second); 378 } 379 CPXchgobj(cplexEnv(), _prob, values.size(), 380 &indices.front(), &values.front()); 381 382 } 383 384 void CplexBase::_getObjCoeffs(InsertIterator b) const 235 385 { 236 int indices[1]; 237 indices[0]=i; 238 char lu[1]; 239 lu[0]='U'; 240 Value bd[1]; 241 bd[0]=value; 242 status = CPXchgbds(env, lp, 1, indices, lu, bd); 243 } 244 245 LpCplex::Value LpCplex::_getColUpperBound(int i) const 386 int num = CPXgetnumcols(cplexEnv(), _prob); 387 std::vector<Value> x(num); 388 389 CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1); 390 for (int i = 0; i < num; ++i) { 391 if (x[i] != 0.0) { 392 *b = std::make_pair(i, x[i]); 393 ++b; 394 } 395 } 396 } 397 398 void CplexBase::_setObjCoeff(int i, Value obj_coef) 246 399 { 247 LpCplex::Value x; 248 CPXgetub (env, lp, &x, i, i); 249 if (x >= CPX_INFBOUND) x = INF; 250 return x; 251 } 252 253 //This will be easier to implement 254 void LpCplex::_setRowBounds(int i, Value lb, Value ub) 255 { 256 //Bad parameter 257 if (lb==INF || ub==-INF) { 258 //FIXME error 259 } 260 261 int cnt=1; 262 int indices[1]; 263 indices[0]=i; 264 char sense[1]; 265 266 if (lb==-INF){ 267 sense[0]='L'; 268 CPXchgsense(env, lp, cnt, indices, sense); 269 CPXchgcoef(env, lp, i, -1, ub); 270 271 } 272 else{ 273 if (ub==INF){ 274 sense[0]='G'; 275 CPXchgsense(env, lp, cnt, indices, sense); 276 CPXchgcoef(env, lp, i, -1, lb); 277 } 278 else{ 279 if (lb == ub){ 280 sense[0]='E'; 281 CPXchgsense(env, lp, cnt, indices, sense); 282 CPXchgcoef(env, lp, i, -1, lb); 283 } 284 else{ 285 sense[0]='R'; 286 CPXchgsense(env, lp, cnt, indices, sense); 287 CPXchgcoef(env, lp, i, -1, lb); 288 CPXchgcoef(env, lp, i, -2, ub-lb); 289 } 290 } 291 } 292 } 293 294 // void LpCplex::_setRowLowerBound(int i, Value value) 295 // { 296 // //Not implemented, obsolete 297 // } 298 299 // void LpCplex::_setRowUpperBound(int i, Value value) 300 // { 301 // //Not implemented, obsolete 302 // // //TODO Ezt kell meg megirni 303 // // //type of the problem 304 // // char sense[1]; 305 // // status = CPXgetsense(env, lp, sense, i, i); 306 // // Value rhs[1]; 307 // // status = CPXgetrhs(env, lp, rhs, i, i); 308 309 // // switch (sense[0]) { 310 // // case 'L'://<= constraint 311 // // break; 312 // // case 'E'://= constraint 313 // // break; 314 // // case 'G'://>= constraint 315 // // break; 316 // // case 'R'://ranged constraint 317 // // break; 318 // // default: ; 319 // // //FIXME error 320 // // } 321 322 // // status = CPXchgcoef(env, lp, i, -2, value_rng); 323 // } 324 325 void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const 326 { 327 char sense; 328 CPXgetsense(env, lp, &sense,i,i); 329 lb=-INF; 330 ub=INF; 331 switch (sense) 332 { 333 case 'L': 334 CPXgetcoef(env, lp, i, -1, &ub); 335 break; 336 case 'G': 337 CPXgetcoef(env, lp, i, -1, &lb); 338 break; 339 case 'E': 340 CPXgetcoef(env, lp, i, -1, &lb); 341 ub=lb; 342 break; 343 case 'R': 344 CPXgetcoef(env, lp, i, -1, &lb); 345 Value x; 346 CPXgetcoef(env, lp, i, -2, &x); 347 ub=lb+x; 348 break; 349 } 350 } 351 352 void LpCplex::_setObjCoeff(int i, Value obj_coef) 353 { 354 CPXchgcoef(env, lp, -1, i, obj_coef); 355 } 356 357 LpCplex::Value LpCplex::_getObjCoeff(int i) const 400 CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef); 401 } 402 403 CplexBase::Value CplexBase::_getObjCoeff(int i) const 358 404 { 359 405 Value x; 360 CPXget coef(env, lp, -1, i, &x);406 CPXgetobj(cplexEnv(), _prob, &x, i, i); 361 407 return x; 362 408 } 363 409 364 void LpCplex::_clearObj() 365 { 366 for (int i=0;i< CPXgetnumcols(env, lp);++i){ 367 CPXchgcoef(env, lp, -1, i, 0); 368 } 369 370 } 410 void CplexBase::_setSense(CplexBase::Sense sense) { 411 switch (sense) { 412 case MIN: 413 CPXchgobjsen(cplexEnv(), _prob, CPX_MIN); 414 break; 415 case MAX: 416 CPXchgobjsen(cplexEnv(), _prob, CPX_MAX); 417 break; 418 } 419 } 420 421 CplexBase::Sense CplexBase::_getSense() const { 422 switch (CPXgetobjsen(cplexEnv(), _prob)) { 423 case CPX_MIN: 424 return MIN; 425 case CPX_MAX: 426 return MAX; 427 default: 428 LEMON_ASSERT(false, "Invalid sense"); 429 return CplexBase::Sense(); 430 } 431 } 432 433 void CplexBase::_clear() { 434 CPXfreeprob(cplexEnv(),&_prob); 435 int status; 436 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); 437 rows.clear(); 438 cols.clear(); 439 } 440 441 // LpCplex members 442 443 LpCplex::LpCplex() 444 : LpBase(), CplexBase(), LpSolver() {} 445 446 LpCplex::LpCplex(const CplexEnv& env) 447 : LpBase(), CplexBase(env), LpSolver() {} 448 449 LpCplex::LpCplex(const LpCplex& other) 450 : LpBase(), CplexBase(other), LpSolver() {} 451 452 LpCplex::~LpCplex() {} 453 454 LpCplex* LpCplex::_newSolver() const { return new LpCplex; } 455 LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); } 456 457 const char* LpCplex::_solverName() const { return "LpCplex"; } 458 459 void LpCplex::_clear_temporals() { 460 _col_status.clear(); 461 _row_status.clear(); 462 _primal_ray.clear(); 463 _dual_ray.clear(); 464 } 465 371 466 // The routine returns zero unless an error occurred during the 372 467 // optimization. Examples of errors include exhausting available … … 378 473 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain 379 474 // further information about the status of the optimization. 380 LpCplex::SolveExitStatus LpCplex::_solve() 381 { 382 //CPX_PARAM_LPMETHOD 383 status = CPXlpopt(env, lp); 384 //status = CPXprimopt(env, lp); 475 LpCplex::SolveExitStatus LpCplex::convertStatus(int status) { 385 476 #if CPX_VERSION >= 800 386 if (status) 387 { 477 if (status == 0) { 478 switch (CPXgetstat(cplexEnv(), _prob)) { 479 case CPX_STAT_OPTIMAL: 480 case CPX_STAT_INFEASIBLE: 481 case CPX_STAT_UNBOUNDED: 482 return SOLVED; 483 default: 484 return UNSOLVED; 485 } 486 } else { 388 487 return UNSOLVED; 389 488 } 390 else391 {392 switch (CPXgetstat(env, lp))393 {394 case CPX_STAT_OPTIMAL:395 case CPX_STAT_INFEASIBLE:396 case CPX_STAT_UNBOUNDED:397 return SOLVED;398 default:399 return UNSOLVED;400 }401 }402 489 #else 403 if (status == 0) {490 if (status == 0) { 404 491 //We want to exclude some cases 405 switch (CPXgetstat( env, lp)){492 switch (CPXgetstat(cplexEnv(), _prob)) { 406 493 case CPX_OBJ_LIM: 407 494 case CPX_IT_LIM_FEAS: … … 413 500 return SOLVED; 414 501 } 415 } 416 else{ 502 } else { 417 503 return UNSOLVED; 418 504 } … … 420 506 } 421 507 422 LpCplex::Value LpCplex::_getPrimal(int i) const 423 { 508 LpCplex::SolveExitStatus LpCplex::_solve() { 509 _clear_temporals(); 510 return convertStatus(CPXlpopt(cplexEnv(), _prob)); 511 } 512 513 LpCplex::SolveExitStatus LpCplex::solvePrimal() { 514 _clear_temporals(); 515 return convertStatus(CPXprimopt(cplexEnv(), _prob)); 516 } 517 518 LpCplex::SolveExitStatus LpCplex::solveDual() { 519 _clear_temporals(); 520 return convertStatus(CPXdualopt(cplexEnv(), _prob)); 521 } 522 523 LpCplex::SolveExitStatus LpCplex::solveBarrier() { 524 _clear_temporals(); 525 return convertStatus(CPXbaropt(cplexEnv(), _prob)); 526 } 527 528 LpCplex::Value LpCplex::_getPrimal(int i) const { 424 529 Value x; 425 CPXgetx( env, lp, &x, i, i);530 CPXgetx(cplexEnv(), _prob, &x, i, i); 426 531 return x; 427 532 } 428 533 429 LpCplex::Value LpCplex::_getDual(int i) const 430 { 534 LpCplex::Value LpCplex::_getDual(int i) const { 431 535 Value y; 432 CPXgetpi( env, lp, &y, i, i);536 CPXgetpi(cplexEnv(), _prob, &y, i, i); 433 537 return y; 434 538 } 435 539 436 LpCplex::Value LpCplex::_getPrimalValue() const 437 { 540 LpCplex::Value LpCplex::_getPrimalValue() const { 438 541 Value objval; 439 //method = CPXgetmethod (env, lp); 440 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp)); 441 CPXgetobjval(env, lp, &objval); 442 //printf("Objective value: %g \n",objval); 542 CPXgetobjval(cplexEnv(), _prob, &objval); 443 543 return objval; 444 544 } 445 bool LpCplex::_isBasicCol(int i) const 446 { 447 std::vector<int> cstat(CPXgetnumcols(env, lp)); 448 CPXgetbase(env, lp, &*cstat.begin(), NULL); 449 return (cstat[i]==CPX_BASIC); 450 } 451 452 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!) 453 // This table lists the statuses, returned by the CPXgetstat() 454 // routine, for solutions to LP problems or mixed integer problems. If 455 // no solution exists, the return value is zero. 456 457 // For Simplex, Barrier 458 // 1 CPX_OPTIMAL 459 // Optimal solution found 460 // 2 CPX_INFEASIBLE 461 // Problem infeasible 462 // 3 CPX_UNBOUNDED 463 // Problem unbounded 464 // 4 CPX_OBJ_LIM 465 // Objective limit exceeded in Phase II 466 // 5 CPX_IT_LIM_FEAS 467 // Iteration limit exceeded in Phase II 468 // 6 CPX_IT_LIM_INFEAS 469 // Iteration limit exceeded in Phase I 470 // 7 CPX_TIME_LIM_FEAS 471 // Time limit exceeded in Phase II 472 // 8 CPX_TIME_LIM_INFEAS 473 // Time limit exceeded in Phase I 474 // 9 CPX_NUM_BEST_FEAS 475 // Problem non-optimal, singularities in Phase II 476 // 10 CPX_NUM_BEST_INFEAS 477 // Problem non-optimal, singularities in Phase I 478 // 11 CPX_OPTIMAL_INFEAS 479 // Optimal solution found, unscaled infeasibilities 480 // 12 CPX_ABORT_FEAS 481 // Aborted in Phase II 482 // 13 CPX_ABORT_INFEAS 483 // Aborted in Phase I 484 // 14 CPX_ABORT_DUAL_INFEAS 485 // Aborted in barrier, dual infeasible 486 // 15 CPX_ABORT_PRIM_INFEAS 487 // Aborted in barrier, primal infeasible 488 // 16 CPX_ABORT_PRIM_DUAL_INFEAS 489 // Aborted in barrier, primal and dual infeasible 490 // 17 CPX_ABORT_PRIM_DUAL_FEAS 491 // Aborted in barrier, primal and dual feasible 492 // 18 CPX_ABORT_CROSSOVER 493 // Aborted in crossover 494 // 19 CPX_INForUNBD 495 // Infeasible or unbounded 496 // 20 CPX_PIVOT 497 // User pivot used 498 // 499 // Ezeket hova tegyem: 500 // ??case CPX_ABORT_DUAL_INFEAS 501 // ??case CPX_ABORT_CROSSOVER 502 // ??case CPX_INForUNBD 503 // ??case CPX_PIVOT 504 505 //Some more interesting stuff: 506 507 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD 508 // 0 Automatic 509 // 1 Primal Simplex 510 // 2 Dual Simplex 511 // 3 Network Simplex 512 // 4 Standard Barrier 513 // Default: 0 514 // Description: Method for linear optimization. 515 // Determines which algorithm is used when CPXlpopt() (or "optimize" 516 // in the Interactive Optimizer) is called. Currently the behavior of 517 // the "Automatic" setting is that CPLEX simply invokes the dual 518 // simplex method, but this capability may be expanded in the future 519 // so that CPLEX chooses the method based on problem characteristics 545 546 LpCplex::VarStatus LpCplex::_getColStatus(int i) const { 547 if (_col_status.empty()) { 548 _col_status.resize(CPXgetnumcols(cplexEnv(), _prob)); 549 CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0); 550 } 551 switch (_col_status[i]) { 552 case CPX_BASIC: 553 return BASIC; 554 case CPX_FREE_SUPER: 555 return FREE; 556 case CPX_AT_LOWER: 557 return LOWER; 558 case CPX_AT_UPPER: 559 return UPPER; 560 default: 561 LEMON_ASSERT(false, "Wrong column status"); 562 return LpCplex::VarStatus(); 563 } 564 } 565 566 LpCplex::VarStatus LpCplex::_getRowStatus(int i) const { 567 if (_row_status.empty()) { 568 _row_status.resize(CPXgetnumrows(cplexEnv(), _prob)); 569 CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front()); 570 } 571 switch (_row_status[i]) { 572 case CPX_BASIC: 573 return BASIC; 574 case CPX_AT_LOWER: 575 { 576 char s; 577 CPXgetsense(cplexEnv(), _prob, &s, i, i); 578 return s != 'L' ? LOWER : UPPER; 579 } 580 case CPX_AT_UPPER: 581 return UPPER; 582 default: 583 LEMON_ASSERT(false, "Wrong row status"); 584 return LpCplex::VarStatus(); 585 } 586 } 587 588 LpCplex::Value LpCplex::_getPrimalRay(int i) const { 589 if (_primal_ray.empty()) { 590 _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob)); 591 CPXgetray(cplexEnv(), _prob, &_primal_ray.front()); 592 } 593 return _primal_ray[i]; 594 } 595 596 LpCplex::Value LpCplex::_getDualRay(int i) const { 597 if (_dual_ray.empty()) { 598 599 } 600 return _dual_ray[i]; 601 } 602 603 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!) 604 // This table lists the statuses, returned by the CPXgetstat() 605 // routine, for solutions to LP problems or mixed integer problems. If 606 // no solution exists, the return value is zero. 607 608 // For Simplex, Barrier 609 // 1 CPX_OPTIMAL 610 // Optimal solution found 611 // 2 CPX_INFEASIBLE 612 // Problem infeasible 613 // 3 CPX_UNBOUNDED 614 // Problem unbounded 615 // 4 CPX_OBJ_LIM 616 // Objective limit exceeded in Phase II 617 // 5 CPX_IT_LIM_FEAS 618 // Iteration limit exceeded in Phase II 619 // 6 CPX_IT_LIM_INFEAS 620 // Iteration limit exceeded in Phase I 621 // 7 CPX_TIME_LIM_FEAS 622 // Time limit exceeded in Phase II 623 // 8 CPX_TIME_LIM_INFEAS 624 // Time limit exceeded in Phase I 625 // 9 CPX_NUM_BEST_FEAS 626 // Problem non-optimal, singularities in Phase II 627 // 10 CPX_NUM_BEST_INFEAS 628 // Problem non-optimal, singularities in Phase I 629 // 11 CPX_OPTIMAL_INFEAS 630 // Optimal solution found, unscaled infeasibilities 631 // 12 CPX_ABORT_FEAS 632 // Aborted in Phase II 633 // 13 CPX_ABORT_INFEAS 634 // Aborted in Phase I 635 // 14 CPX_ABORT_DUAL_INFEAS 636 // Aborted in barrier, dual infeasible 637 // 15 CPX_ABORT_PRIM_INFEAS 638 // Aborted in barrier, primal infeasible 639 // 16 CPX_ABORT_PRIM_DUAL_INFEAS 640 // Aborted in barrier, primal and dual infeasible 641 // 17 CPX_ABORT_PRIM_DUAL_FEAS 642 // Aborted in barrier, primal and dual feasible 643 // 18 CPX_ABORT_CROSSOVER 644 // Aborted in crossover 645 // 19 CPX_INForUNBD 646 // Infeasible or unbounded 647 // 20 CPX_PIVOT 648 // User pivot used 649 // 650 // Ezeket hova tegyem: 651 // ??case CPX_ABORT_DUAL_INFEAS 652 // ??case CPX_ABORT_CROSSOVER 653 // ??case CPX_INForUNBD 654 // ??case CPX_PIVOT 655 656 //Some more interesting stuff: 657 658 // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD 659 // 0 Automatic 660 // 1 Primal Simplex 661 // 2 Dual Simplex 662 // 3 Network Simplex 663 // 4 Standard Barrier 664 // Default: 0 665 // Description: Method for linear optimization. 666 // Determines which algorithm is used when CPXlpopt() (or "optimize" 667 // in the Interactive Optimizer) is called. Currently the behavior of 668 // the "Automatic" setting is that CPLEX simply invokes the dual 669 // simplex method, but this capability may be expanded in the future 670 // so that CPLEX chooses the method based on problem characteristics 520 671 #if CPX_VERSION < 900 521 void statusSwitch(CPXENVptr env,int& stat){672 void statusSwitch(CPXENVptr cplexEnv(),int& stat){ 522 673 int lpmethod; 523 CPXgetintparam ( env,CPX_PARAM_LPMETHOD,&lpmethod);674 CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod); 524 675 if (lpmethod==2){ 525 676 if (stat==CPX_UNBOUNDED){ … … 536 687 #endif 537 688 538 LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const 539 { 540 //Unboundedness not treated well: the following is from cplex 9.0 doc 689 LpCplex::ProblemType LpCplex::_getPrimalType() const { 690 // Unboundedness not treated well: the following is from cplex 9.0 doc 541 691 // About Unboundedness 542 692 … … 553 703 // has a feasible solution. 554 704 555 int stat = CPXgetstat( env, lp);705 int stat = CPXgetstat(cplexEnv(), _prob); 556 706 #if CPX_VERSION >= 800 557 707 switch (stat) 558 {708 { 559 709 case CPX_STAT_OPTIMAL: 560 710 return OPTIMAL; 561 711 case CPX_STAT_UNBOUNDED: 562 return INFINITE;712 return UNBOUNDED; 563 713 case CPX_STAT_INFEASIBLE: 564 714 return INFEASIBLE; 565 715 default: 566 716 return UNDEFINED; 567 }717 } 568 718 #else 569 statusSwitch( env,stat);570 //CPXgetstat( env, lp);719 statusSwitch(cplexEnv(),stat); 720 //CPXgetstat(cplexEnv(), _prob); 571 721 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL); 572 722 switch (stat) { … … 577 727 case CPX_UNBOUNDED://Unbounded 578 728 return INFEASIBLE;//In case of dual simplex 579 //return INFINITE;729 //return UNBOUNDED; 580 730 case CPX_INFEASIBLE://Infeasible 581 // case CPX_IT_LIM_INFEAS:582 // case CPX_TIME_LIM_INFEAS:583 // case CPX_NUM_BEST_INFEAS:584 // case CPX_OPTIMAL_INFEAS:585 // case CPX_ABORT_INFEAS:586 // case CPX_ABORT_PRIM_INFEAS:587 // case CPX_ABORT_PRIM_DUAL_INFEAS:588 return INFINITE;//In case of dual simplex731 // case CPX_IT_LIM_INFEAS: 732 // case CPX_TIME_LIM_INFEAS: 733 // case CPX_NUM_BEST_INFEAS: 734 // case CPX_OPTIMAL_INFEAS: 735 // case CPX_ABORT_INFEAS: 736 // case CPX_ABORT_PRIM_INFEAS: 737 // case CPX_ABORT_PRIM_DUAL_INFEAS: 738 return UNBOUNDED;//In case of dual simplex 589 739 //return INFEASIBLE; 590 // case CPX_OBJ_LIM:591 // case CPX_IT_LIM_FEAS:592 // case CPX_TIME_LIM_FEAS:593 // case CPX_NUM_BEST_FEAS:594 // case CPX_ABORT_FEAS:595 // case CPX_ABORT_PRIM_DUAL_FEAS:596 // return FEASIBLE;740 // case CPX_OBJ_LIM: 741 // case CPX_IT_LIM_FEAS: 742 // case CPX_TIME_LIM_FEAS: 743 // case CPX_NUM_BEST_FEAS: 744 // case CPX_ABORT_FEAS: 745 // case CPX_ABORT_PRIM_DUAL_FEAS: 746 // return FEASIBLE; 597 747 default: 598 748 return UNDEFINED; //Everything else comes here … … 602 752 } 603 753 604 //9.0-as cplex verzio statusai 605 // CPX_STAT_ABORT_DUAL_OBJ_LIM 606 // CPX_STAT_ABORT_IT_LIM 607 // CPX_STAT_ABORT_OBJ_LIM 608 // CPX_STAT_ABORT_PRIM_OBJ_LIM 609 // CPX_STAT_ABORT_TIME_LIM 610 // CPX_STAT_ABORT_USER 611 // CPX_STAT_FEASIBLE_RELAXED 612 // CPX_STAT_INFEASIBLE 613 // CPX_STAT_INForUNBD 614 // CPX_STAT_NUM_BEST 615 // CPX_STAT_OPTIMAL 616 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED 617 // CPX_STAT_OPTIMAL_INFEAS 618 // CPX_STAT_OPTIMAL_RELAXED 619 // CPX_STAT_UNBOUNDED 620 621 LpCplex::SolutionStatus LpCplex::_getDualStatus() const 622 { 623 int stat = CPXgetstat(env, lp); 754 //9.0-as cplex verzio statusai 755 // CPX_STAT_ABORT_DUAL_OBJ_LIM 756 // CPX_STAT_ABORT_IT_LIM 757 // CPX_STAT_ABORT_OBJ_LIM 758 // CPX_STAT_ABORT_PRIM_OBJ_LIM 759 // CPX_STAT_ABORT_TIME_LIM 760 // CPX_STAT_ABORT_USER 761 // CPX_STAT_FEASIBLE_RELAXED 762 // CPX_STAT_INFEASIBLE 763 // CPX_STAT_INForUNBD 764 // CPX_STAT_NUM_BEST 765 // CPX_STAT_OPTIMAL 766 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED 767 // CPX_STAT_OPTIMAL_INFEAS 768 // CPX_STAT_OPTIMAL_RELAXED 769 // CPX_STAT_UNBOUNDED 770 771 LpCplex::ProblemType LpCplex::_getDualType() const { 772 int stat = CPXgetstat(cplexEnv(), _prob); 624 773 #if CPX_VERSION >= 800 625 switch (stat) 626 { 627 case CPX_STAT_OPTIMAL: 628 return OPTIMAL; 629 case CPX_STAT_UNBOUNDED: 630 return INFEASIBLE; 631 default: 632 return UNDEFINED; 774 switch (stat) { 775 case CPX_STAT_OPTIMAL: 776 return OPTIMAL; 777 case CPX_STAT_UNBOUNDED: 778 return INFEASIBLE; 779 default: 780 return UNDEFINED; 633 781 } 634 782 #else 635 statusSwitch( env,stat);783 statusSwitch(cplexEnv(),stat); 636 784 switch (stat) { 637 785 case 0: … … 640 788 return OPTIMAL; 641 789 case CPX_UNBOUNDED: 642 return INFEASIBLE;790 return INFEASIBLE; 643 791 default: 644 792 return UNDEFINED; //Everything else comes here … … 648 796 } 649 797 650 LpCplex::ProblemTypes LpCplex::_getProblemType() const 651 { 652 int stat = CPXgetstat(env, lp); 653 #if CPX_VERSION >= 800 654 switch (stat) 655 { 656 case CPX_STAT_OPTIMAL: 657 return PRIMAL_DUAL_FEASIBLE; 658 case CPX_STAT_UNBOUNDED: 659 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; 660 default: 661 return UNKNOWN; 662 } 798 // MipCplex members 799 800 MipCplex::MipCplex() 801 : LpBase(), CplexBase(), MipSolver() { 802 803 #if CPX_VERSION < 800 804 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP); 663 805 #else 806 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP); 807 #endif 808 } 809 810 MipCplex::MipCplex(const CplexEnv& env) 811 : LpBase(), CplexBase(env), MipSolver() { 812 813 #if CPX_VERSION < 800 814 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP); 815 #else 816 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP); 817 #endif 818 819 } 820 821 MipCplex::MipCplex(const MipCplex& other) 822 : LpBase(), CplexBase(other), MipSolver() {} 823 824 MipCplex::~MipCplex() {} 825 826 MipCplex* MipCplex::_newSolver() const { return new MipCplex; } 827 MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); } 828 829 const char* MipCplex::_solverName() const { return "MipCplex"; } 830 831 void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) { 832 833 // Note If a variable is to be changed to binary, a call to CPXchgbds 834 // should also be made to change the bounds to 0 and 1. 835 836 switch (col_type){ 837 case INTEGER: { 838 const char t = 'I'; 839 CPXchgctype (cplexEnv(), _prob, 1, &i, &t); 840 } break; 841 case REAL: { 842 const char t = 'C'; 843 CPXchgctype (cplexEnv(), _prob, 1, &i, &t); 844 } break; 845 default: 846 break; 847 } 848 } 849 850 MipCplex::ColTypes MipCplex::_getColType(int i) const { 851 char t; 852 CPXgetctype (cplexEnv(), _prob, &t, i, i); 853 switch (t) { 854 case 'I': 855 return INTEGER; 856 case 'C': 857 return REAL; 858 default: 859 LEMON_ASSERT(false, "Invalid column type"); 860 return ColTypes(); 861 } 862 863 } 864 865 MipCplex::SolveExitStatus MipCplex::_solve() { 866 int status; 867 status = CPXmipopt (cplexEnv(), _prob); 868 if (status==0) 869 return SOLVED; 870 else 871 return UNSOLVED; 872 873 } 874 875 876 MipCplex::ProblemType MipCplex::_getType() const { 877 878 int stat = CPXgetstat(cplexEnv(), _prob); 879 880 //Fortunately, MIP statuses did not change for cplex 8.0 664 881 switch (stat) { 665 case CPX_OPTIMAL://Optimal 666 return PRIMAL_DUAL_FEASIBLE; 667 case CPX_UNBOUNDED: 668 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; 669 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE; 670 // return PRIMAL_DUAL_INFEASIBLE; 671 672 //Seems to be that this is all we can say for sure 673 default: 674 //In all other cases 675 return UNKNOWN; 676 //FIXME error 677 } 678 #endif 679 } 680 681 void LpCplex::_setMax() 682 { 683 CPXchgobjsen(env, lp, CPX_MAX); 684 } 685 void LpCplex::_setMin() 686 { 687 CPXchgobjsen(env, lp, CPX_MIN); 688 } 689 690 bool LpCplex::_isMax() const 691 { 692 if (CPXgetobjsen(env, lp)==CPX_MAX) 693 return true; 694 else 695 return false; 882 case CPXMIP_OPTIMAL: 883 // Optimal integer solution has been found. 884 case CPXMIP_OPTIMAL_TOL: 885 // Optimal soluton with the tolerance defined by epgap or epagap has 886 // been found. 887 return OPTIMAL; 888 //This also exists in later issues 889 // case CPXMIP_UNBOUNDED: 890 //return UNBOUNDED; 891 case CPXMIP_INFEASIBLE: 892 return INFEASIBLE; 893 default: 894 return UNDEFINED; 895 } 896 //Unboundedness not treated well: the following is from cplex 9.0 doc 897 // About Unboundedness 898 899 // The treatment of models that are unbounded involves a few 900 // subtleties. Specifically, a declaration of unboundedness means that 901 // ILOG CPLEX has determined that the model has an unbounded 902 // ray. Given any feasible solution x with objective z, a multiple of 903 // the unbounded ray can be added to x to give a feasible solution 904 // with objective z-1 (or z+1 for maximization models). Thus, if a 905 // feasible solution exists, then the optimal objective is 906 // unbounded. Note that ILOG CPLEX has not necessarily concluded that 907 // a feasible solution exists. Users can call the routine CPXsolninfo 908 // to determine whether ILOG CPLEX has also concluded that the model 909 // has a feasible solution. 910 } 911 912 MipCplex::Value MipCplex::_getSol(int i) const { 913 Value x; 914 CPXgetmipx(cplexEnv(), _prob, &x, i, i); 915 return x; 916 } 917 918 MipCplex::Value MipCplex::_getSolValue() const { 919 Value objval; 920 CPXgetmipobjval(cplexEnv(), _prob, &objval); 921 return objval; 696 922 } 697 923
Note: See TracChangeset
for help on using the changeset viewer.