1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/lemon/lp_cplex.cc Tue Dec 02 21:40:33 2008 +0100
1.3 @@ -0,0 +1,699 @@
1.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
1.5 + *
1.6 + * This file is a part of LEMON, a generic C++ optimization library.
1.7 + *
1.8 + * Copyright (C) 2003-2008
1.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 + *
1.12 + * Permission to use, modify and distribute this software is granted
1.13 + * provided that this copyright notice appears in all copies. For
1.14 + * precise terms see the accompanying LICENSE file.
1.15 + *
1.16 + * This software is provided "AS IS" with no warranty of any kind,
1.17 + * express or implied, and with no claim as to its suitability for any
1.18 + * purpose.
1.19 + *
1.20 + */
1.21 +
1.22 +#include <iostream>
1.23 +#include <vector>
1.24 +#include <lemon/lp_cplex.h>
1.25 +
1.26 +extern "C" {
1.27 +#include <ilcplex/cplex.h>
1.28 +}
1.29 +
1.30 +
1.31 +///\file
1.32 +///\brief Implementation of the LEMON-CPLEX lp solver interface.
1.33 +namespace lemon {
1.34 +
1.35 + LpCplex::LpCplex() {
1.36 + // env = CPXopenCPLEXdevelop(&status);
1.37 + env = CPXopenCPLEX(&status);
1.38 + lp = CPXcreateprob(env, &status, "LP problem");
1.39 + }
1.40 +
1.41 + LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
1.42 + env = CPXopenCPLEX(&status);
1.43 + lp = CPXcloneprob(env, cplex.lp, &status);
1.44 + rows = cplex.rows;
1.45 + cols = cplex.cols;
1.46 + }
1.47 +
1.48 + LpCplex::~LpCplex() {
1.49 + CPXfreeprob(env,&lp);
1.50 + CPXcloseCPLEX(&env);
1.51 + }
1.52 +
1.53 + LpSolverBase* LpCplex::_newLp()
1.54 + {
1.55 + //The first approach opens a new environment
1.56 + return new LpCplex();
1.57 + }
1.58 +
1.59 + LpSolverBase* LpCplex::_copyLp() {
1.60 + return new LpCplex(*this);
1.61 + }
1.62 +
1.63 + int LpCplex::_addCol()
1.64 + {
1.65 + int i = CPXgetnumcols(env, lp);
1.66 + Value lb[1],ub[1];
1.67 + lb[0]=-INF;
1.68 + ub[0]=INF;
1.69 + status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
1.70 + return i;
1.71 + }
1.72 +
1.73 +
1.74 + int LpCplex::_addRow()
1.75 + {
1.76 + //We want a row that is not constrained
1.77 + char sense[1];
1.78 + sense[0]='L';//<= constraint
1.79 + Value rhs[1];
1.80 + rhs[0]=INF;
1.81 + int i = CPXgetnumrows(env, lp);
1.82 + status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
1.83 + return i;
1.84 + }
1.85 +
1.86 +
1.87 + void LpCplex::_eraseCol(int i) {
1.88 + CPXdelcols(env, lp, i, i);
1.89 + }
1.90 +
1.91 + void LpCplex::_eraseRow(int i) {
1.92 + CPXdelrows(env, lp, i, i);
1.93 + }
1.94 +
1.95 + void LpCplex::_getColName(int col, std::string &name) const
1.96 + {
1.97 + ///\bug Untested
1.98 + int storespace;
1.99 + CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
1.100 + if (storespace == 0) {
1.101 + name.clear();
1.102 + return;
1.103 + }
1.104 +
1.105 + storespace *= -1;
1.106 + std::vector<char> buf(storespace);
1.107 + char *names[1];
1.108 + int dontcare;
1.109 + ///\bug return code unchecked for error
1.110 + CPXgetcolname(env, lp, names, &*buf.begin(), storespace,
1.111 + &dontcare, col, col);
1.112 + name = names[0];
1.113 + }
1.114 +
1.115 + void LpCplex::_setColName(int col, const std::string &name)
1.116 + {
1.117 + ///\bug Untested
1.118 + char *names[1];
1.119 + names[0] = const_cast<char*>(name.c_str());
1.120 + ///\bug return code unchecked for error
1.121 + CPXchgcolname(env, lp, 1, &col, names);
1.122 + }
1.123 +
1.124 + int LpCplex::_colByName(const std::string& name) const
1.125 + {
1.126 + int index;
1.127 + if (CPXgetcolindex(env, lp,
1.128 + const_cast<char*>(name.c_str()), &index) == 0) {
1.129 + return index;
1.130 + }
1.131 + return -1;
1.132 + }
1.133 +
1.134 + ///\warning Data at index 0 is ignored in the arrays.
1.135 + void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
1.136 + {
1.137 + std::vector<int> indices;
1.138 + std::vector<int> rowlist;
1.139 + std::vector<Value> values;
1.140 +
1.141 + for(ConstRowIterator it=b; it!=e; ++it) {
1.142 + indices.push_back(it->first);
1.143 + values.push_back(it->second);
1.144 + rowlist.push_back(i);
1.145 + }
1.146 +
1.147 + status = CPXchgcoeflist(env, lp, values.size(),
1.148 + &rowlist[0], &indices[0], &values[0]);
1.149 + }
1.150 +
1.151 + void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
1.152 + int tmp1, tmp2, tmp3, length;
1.153 + CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
1.154 +
1.155 + length = -length;
1.156 + std::vector<int> indices(length);
1.157 + std::vector<double> values(length);
1.158 +
1.159 + CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
1.160 + length, &tmp3, i, i);
1.161 +
1.162 + for (int i = 0; i < length; ++i) {
1.163 + *b = std::make_pair(indices[i], values[i]);
1.164 + ++b;
1.165 + }
1.166 +
1.167 + /// \todo implement
1.168 + }
1.169 +
1.170 + void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
1.171 + {
1.172 + std::vector<int> indices;
1.173 + std::vector<int> collist;
1.174 + std::vector<Value> values;
1.175 +
1.176 + for(ConstColIterator it=b; it!=e; ++it) {
1.177 + indices.push_back(it->first);
1.178 + values.push_back(it->second);
1.179 + collist.push_back(i);
1.180 + }
1.181 +
1.182 + status = CPXchgcoeflist(env, lp, values.size(),
1.183 + &indices[0], &collist[0], &values[0]);
1.184 + }
1.185 +
1.186 + void LpCplex::_getColCoeffs(int i, ColIterator b) const {
1.187 +
1.188 + int tmp1, tmp2, tmp3, length;
1.189 + CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
1.190 +
1.191 + length = -length;
1.192 + std::vector<int> indices(length);
1.193 + std::vector<double> values(length);
1.194 +
1.195 + CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
1.196 + length, &tmp3, i, i);
1.197 +
1.198 + for (int i = 0; i < length; ++i) {
1.199 + *b = std::make_pair(indices[i], values[i]);
1.200 + ++b;
1.201 + }
1.202 +
1.203 + }
1.204 +
1.205 + void LpCplex::_setCoeff(int row, int col, Value value)
1.206 + {
1.207 + CPXchgcoef(env, lp, row, col, value);
1.208 + }
1.209 +
1.210 + LpCplex::Value LpCplex::_getCoeff(int row, int col) const
1.211 + {
1.212 + LpCplex::Value value;
1.213 + CPXgetcoef(env, lp, row, col, &value);
1.214 + return value;
1.215 + }
1.216 +
1.217 + void LpCplex::_setColLowerBound(int i, Value value)
1.218 + {
1.219 + int indices[1];
1.220 + indices[0]=i;
1.221 + char lu[1];
1.222 + lu[0]='L';
1.223 + Value bd[1];
1.224 + bd[0]=value;
1.225 + status = CPXchgbds(env, lp, 1, indices, lu, bd);
1.226 +
1.227 + }
1.228 +
1.229 + LpCplex::Value LpCplex::_getColLowerBound(int i) const
1.230 + {
1.231 + LpCplex::Value x;
1.232 + CPXgetlb (env, lp, &x, i, i);
1.233 + if (x <= -CPX_INFBOUND) x = -INF;
1.234 + return x;
1.235 + }
1.236 +
1.237 + void LpCplex::_setColUpperBound(int i, Value value)
1.238 + {
1.239 + int indices[1];
1.240 + indices[0]=i;
1.241 + char lu[1];
1.242 + lu[0]='U';
1.243 + Value bd[1];
1.244 + bd[0]=value;
1.245 + status = CPXchgbds(env, lp, 1, indices, lu, bd);
1.246 + }
1.247 +
1.248 + LpCplex::Value LpCplex::_getColUpperBound(int i) const
1.249 + {
1.250 + LpCplex::Value x;
1.251 + CPXgetub (env, lp, &x, i, i);
1.252 + if (x >= CPX_INFBOUND) x = INF;
1.253 + return x;
1.254 + }
1.255 +
1.256 + //This will be easier to implement
1.257 + void LpCplex::_setRowBounds(int i, Value lb, Value ub)
1.258 + {
1.259 + //Bad parameter
1.260 + if (lb==INF || ub==-INF) {
1.261 + //FIXME error
1.262 + }
1.263 +
1.264 + int cnt=1;
1.265 + int indices[1];
1.266 + indices[0]=i;
1.267 + char sense[1];
1.268 +
1.269 + if (lb==-INF){
1.270 + sense[0]='L';
1.271 + CPXchgsense(env, lp, cnt, indices, sense);
1.272 + CPXchgcoef(env, lp, i, -1, ub);
1.273 +
1.274 + }
1.275 + else{
1.276 + if (ub==INF){
1.277 + sense[0]='G';
1.278 + CPXchgsense(env, lp, cnt, indices, sense);
1.279 + CPXchgcoef(env, lp, i, -1, lb);
1.280 + }
1.281 + else{
1.282 + if (lb == ub){
1.283 + sense[0]='E';
1.284 + CPXchgsense(env, lp, cnt, indices, sense);
1.285 + CPXchgcoef(env, lp, i, -1, lb);
1.286 + }
1.287 + else{
1.288 + sense[0]='R';
1.289 + CPXchgsense(env, lp, cnt, indices, sense);
1.290 + CPXchgcoef(env, lp, i, -1, lb);
1.291 + CPXchgcoef(env, lp, i, -2, ub-lb);
1.292 + }
1.293 + }
1.294 + }
1.295 + }
1.296 +
1.297 +// void LpCplex::_setRowLowerBound(int i, Value value)
1.298 +// {
1.299 +// //Not implemented, obsolete
1.300 +// }
1.301 +
1.302 +// void LpCplex::_setRowUpperBound(int i, Value value)
1.303 +// {
1.304 +// //Not implemented, obsolete
1.305 +// // //TODO Ezt kell meg megirni
1.306 +// // //type of the problem
1.307 +// // char sense[1];
1.308 +// // status = CPXgetsense(env, lp, sense, i, i);
1.309 +// // Value rhs[1];
1.310 +// // status = CPXgetrhs(env, lp, rhs, i, i);
1.311 +
1.312 +// // switch (sense[0]) {
1.313 +// // case 'L'://<= constraint
1.314 +// // break;
1.315 +// // case 'E'://= constraint
1.316 +// // break;
1.317 +// // case 'G'://>= constraint
1.318 +// // break;
1.319 +// // case 'R'://ranged constraint
1.320 +// // break;
1.321 +// // default: ;
1.322 +// // //FIXME error
1.323 +// // }
1.324 +
1.325 +// // status = CPXchgcoef(env, lp, i, -2, value_rng);
1.326 +// }
1.327 +
1.328 + void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
1.329 + {
1.330 + char sense;
1.331 + CPXgetsense(env, lp, &sense,i,i);
1.332 + lb=-INF;
1.333 + ub=INF;
1.334 + switch (sense)
1.335 + {
1.336 + case 'L':
1.337 + CPXgetcoef(env, lp, i, -1, &ub);
1.338 + break;
1.339 + case 'G':
1.340 + CPXgetcoef(env, lp, i, -1, &lb);
1.341 + break;
1.342 + case 'E':
1.343 + CPXgetcoef(env, lp, i, -1, &lb);
1.344 + ub=lb;
1.345 + break;
1.346 + case 'R':
1.347 + CPXgetcoef(env, lp, i, -1, &lb);
1.348 + Value x;
1.349 + CPXgetcoef(env, lp, i, -2, &x);
1.350 + ub=lb+x;
1.351 + break;
1.352 + }
1.353 + }
1.354 +
1.355 + void LpCplex::_setObjCoeff(int i, Value obj_coef)
1.356 + {
1.357 + CPXchgcoef(env, lp, -1, i, obj_coef);
1.358 + }
1.359 +
1.360 + LpCplex::Value LpCplex::_getObjCoeff(int i) const
1.361 + {
1.362 + Value x;
1.363 + CPXgetcoef(env, lp, -1, i, &x);
1.364 + return x;
1.365 + }
1.366 +
1.367 + void LpCplex::_clearObj()
1.368 + {
1.369 + for (int i=0;i< CPXgetnumcols(env, lp);++i){
1.370 + CPXchgcoef(env, lp, -1, i, 0);
1.371 + }
1.372 +
1.373 + }
1.374 + // The routine returns zero unless an error occurred during the
1.375 + // optimization. Examples of errors include exhausting available
1.376 + // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
1.377 + // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
1.378 + // user-specified CPLEX limit, or proving the model infeasible or
1.379 + // unbounded, are not considered errors. Note that a zero return
1.380 + // value does not necessarily mean that a solution exists. Use query
1.381 + // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
1.382 + // further information about the status of the optimization.
1.383 + LpCplex::SolveExitStatus LpCplex::_solve()
1.384 + {
1.385 + //CPX_PARAM_LPMETHOD
1.386 + status = CPXlpopt(env, lp);
1.387 + //status = CPXprimopt(env, lp);
1.388 +#if CPX_VERSION >= 800
1.389 + if (status)
1.390 + {
1.391 + return UNSOLVED;
1.392 + }
1.393 + else
1.394 + {
1.395 + switch (CPXgetstat(env, lp))
1.396 + {
1.397 + case CPX_STAT_OPTIMAL:
1.398 + case CPX_STAT_INFEASIBLE:
1.399 + case CPX_STAT_UNBOUNDED:
1.400 + return SOLVED;
1.401 + default:
1.402 + return UNSOLVED;
1.403 + }
1.404 + }
1.405 +#else
1.406 + if (status == 0){
1.407 + //We want to exclude some cases
1.408 + switch (CPXgetstat(env, lp)){
1.409 + case CPX_OBJ_LIM:
1.410 + case CPX_IT_LIM_FEAS:
1.411 + case CPX_IT_LIM_INFEAS:
1.412 + case CPX_TIME_LIM_FEAS:
1.413 + case CPX_TIME_LIM_INFEAS:
1.414 + return UNSOLVED;
1.415 + default:
1.416 + return SOLVED;
1.417 + }
1.418 + }
1.419 + else{
1.420 + return UNSOLVED;
1.421 + }
1.422 +#endif
1.423 + }
1.424 +
1.425 + LpCplex::Value LpCplex::_getPrimal(int i) const
1.426 + {
1.427 + Value x;
1.428 + CPXgetx(env, lp, &x, i, i);
1.429 + return x;
1.430 + }
1.431 +
1.432 + LpCplex::Value LpCplex::_getDual(int i) const
1.433 + {
1.434 + Value y;
1.435 + CPXgetpi(env, lp, &y, i, i);
1.436 + return y;
1.437 + }
1.438 +
1.439 + LpCplex::Value LpCplex::_getPrimalValue() const
1.440 + {
1.441 + Value objval;
1.442 + //method = CPXgetmethod (env, lp);
1.443 + //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
1.444 + CPXgetobjval(env, lp, &objval);
1.445 + //printf("Objective value: %g \n",objval);
1.446 + return objval;
1.447 + }
1.448 + bool LpCplex::_isBasicCol(int i) const
1.449 + {
1.450 + std::vector<int> cstat(CPXgetnumcols(env, lp));
1.451 + CPXgetbase(env, lp, &*cstat.begin(), NULL);
1.452 + return (cstat[i]==CPX_BASIC);
1.453 + }
1.454 +
1.455 +//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
1.456 +// This table lists the statuses, returned by the CPXgetstat()
1.457 +// routine, for solutions to LP problems or mixed integer problems. If
1.458 +// no solution exists, the return value is zero.
1.459 +
1.460 +// For Simplex, Barrier
1.461 +// 1 CPX_OPTIMAL
1.462 +// Optimal solution found
1.463 +// 2 CPX_INFEASIBLE
1.464 +// Problem infeasible
1.465 +// 3 CPX_UNBOUNDED
1.466 +// Problem unbounded
1.467 +// 4 CPX_OBJ_LIM
1.468 +// Objective limit exceeded in Phase II
1.469 +// 5 CPX_IT_LIM_FEAS
1.470 +// Iteration limit exceeded in Phase II
1.471 +// 6 CPX_IT_LIM_INFEAS
1.472 +// Iteration limit exceeded in Phase I
1.473 +// 7 CPX_TIME_LIM_FEAS
1.474 +// Time limit exceeded in Phase II
1.475 +// 8 CPX_TIME_LIM_INFEAS
1.476 +// Time limit exceeded in Phase I
1.477 +// 9 CPX_NUM_BEST_FEAS
1.478 +// Problem non-optimal, singularities in Phase II
1.479 +// 10 CPX_NUM_BEST_INFEAS
1.480 +// Problem non-optimal, singularities in Phase I
1.481 +// 11 CPX_OPTIMAL_INFEAS
1.482 +// Optimal solution found, unscaled infeasibilities
1.483 +// 12 CPX_ABORT_FEAS
1.484 +// Aborted in Phase II
1.485 +// 13 CPX_ABORT_INFEAS
1.486 +// Aborted in Phase I
1.487 +// 14 CPX_ABORT_DUAL_INFEAS
1.488 +// Aborted in barrier, dual infeasible
1.489 +// 15 CPX_ABORT_PRIM_INFEAS
1.490 +// Aborted in barrier, primal infeasible
1.491 +// 16 CPX_ABORT_PRIM_DUAL_INFEAS
1.492 +// Aborted in barrier, primal and dual infeasible
1.493 +// 17 CPX_ABORT_PRIM_DUAL_FEAS
1.494 +// Aborted in barrier, primal and dual feasible
1.495 +// 18 CPX_ABORT_CROSSOVER
1.496 +// Aborted in crossover
1.497 +// 19 CPX_INForUNBD
1.498 +// Infeasible or unbounded
1.499 +// 20 CPX_PIVOT
1.500 +// User pivot used
1.501 +//
1.502 +// Ezeket hova tegyem:
1.503 +// ??case CPX_ABORT_DUAL_INFEAS
1.504 +// ??case CPX_ABORT_CROSSOVER
1.505 +// ??case CPX_INForUNBD
1.506 +// ??case CPX_PIVOT
1.507 +
1.508 +//Some more interesting stuff:
1.509 +
1.510 +// CPX_PARAM_LPMETHOD 1062 int LPMETHOD
1.511 +// 0 Automatic
1.512 +// 1 Primal Simplex
1.513 +// 2 Dual Simplex
1.514 +// 3 Network Simplex
1.515 +// 4 Standard Barrier
1.516 +// Default: 0
1.517 +// Description: Method for linear optimization.
1.518 +// Determines which algorithm is used when CPXlpopt() (or "optimize"
1.519 +// in the Interactive Optimizer) is called. Currently the behavior of
1.520 +// the "Automatic" setting is that CPLEX simply invokes the dual
1.521 +// simplex method, but this capability may be expanded in the future
1.522 +// so that CPLEX chooses the method based on problem characteristics
1.523 +#if CPX_VERSION < 900
1.524 + void statusSwitch(CPXENVptr env,int& stat){
1.525 + int lpmethod;
1.526 + CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
1.527 + if (lpmethod==2){
1.528 + if (stat==CPX_UNBOUNDED){
1.529 + stat=CPX_INFEASIBLE;
1.530 + }
1.531 + else{
1.532 + if (stat==CPX_INFEASIBLE)
1.533 + stat=CPX_UNBOUNDED;
1.534 + }
1.535 + }
1.536 + }
1.537 +#else
1.538 + void statusSwitch(CPXENVptr,int&){}
1.539 +#endif
1.540 +
1.541 + LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
1.542 + {
1.543 + //Unboundedness not treated well: the following is from cplex 9.0 doc
1.544 + // About Unboundedness
1.545 +
1.546 + // The treatment of models that are unbounded involves a few
1.547 + // subtleties. Specifically, a declaration of unboundedness means that
1.548 + // ILOG CPLEX has determined that the model has an unbounded
1.549 + // ray. Given any feasible solution x with objective z, a multiple of
1.550 + // the unbounded ray can be added to x to give a feasible solution
1.551 + // with objective z-1 (or z+1 for maximization models). Thus, if a
1.552 + // feasible solution exists, then the optimal objective is
1.553 + // unbounded. Note that ILOG CPLEX has not necessarily concluded that
1.554 + // a feasible solution exists. Users can call the routine CPXsolninfo
1.555 + // to determine whether ILOG CPLEX has also concluded that the model
1.556 + // has a feasible solution.
1.557 +
1.558 + int stat = CPXgetstat(env, lp);
1.559 +#if CPX_VERSION >= 800
1.560 + switch (stat)
1.561 + {
1.562 + case CPX_STAT_OPTIMAL:
1.563 + return OPTIMAL;
1.564 + case CPX_STAT_UNBOUNDED:
1.565 + return INFINITE;
1.566 + case CPX_STAT_INFEASIBLE:
1.567 + return INFEASIBLE;
1.568 + default:
1.569 + return UNDEFINED;
1.570 + }
1.571 +#else
1.572 + statusSwitch(env,stat);
1.573 + //CPXgetstat(env, lp);
1.574 + //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
1.575 + switch (stat) {
1.576 + case 0:
1.577 + return UNDEFINED; //Undefined
1.578 + case CPX_OPTIMAL://Optimal
1.579 + return OPTIMAL;
1.580 + case CPX_UNBOUNDED://Unbounded
1.581 + return INFEASIBLE;//In case of dual simplex
1.582 + //return INFINITE;
1.583 + case CPX_INFEASIBLE://Infeasible
1.584 + // case CPX_IT_LIM_INFEAS:
1.585 +// case CPX_TIME_LIM_INFEAS:
1.586 +// case CPX_NUM_BEST_INFEAS:
1.587 +// case CPX_OPTIMAL_INFEAS:
1.588 +// case CPX_ABORT_INFEAS:
1.589 +// case CPX_ABORT_PRIM_INFEAS:
1.590 +// case CPX_ABORT_PRIM_DUAL_INFEAS:
1.591 + return INFINITE;//In case of dual simplex
1.592 + //return INFEASIBLE;
1.593 +// case CPX_OBJ_LIM:
1.594 +// case CPX_IT_LIM_FEAS:
1.595 +// case CPX_TIME_LIM_FEAS:
1.596 +// case CPX_NUM_BEST_FEAS:
1.597 +// case CPX_ABORT_FEAS:
1.598 +// case CPX_ABORT_PRIM_DUAL_FEAS:
1.599 +// return FEASIBLE;
1.600 + default:
1.601 + return UNDEFINED; //Everything else comes here
1.602 + //FIXME error
1.603 + }
1.604 +#endif
1.605 + }
1.606 +
1.607 +//9.0-as cplex verzio statusai
1.608 +// CPX_STAT_ABORT_DUAL_OBJ_LIM
1.609 +// CPX_STAT_ABORT_IT_LIM
1.610 +// CPX_STAT_ABORT_OBJ_LIM
1.611 +// CPX_STAT_ABORT_PRIM_OBJ_LIM
1.612 +// CPX_STAT_ABORT_TIME_LIM
1.613 +// CPX_STAT_ABORT_USER
1.614 +// CPX_STAT_FEASIBLE_RELAXED
1.615 +// CPX_STAT_INFEASIBLE
1.616 +// CPX_STAT_INForUNBD
1.617 +// CPX_STAT_NUM_BEST
1.618 +// CPX_STAT_OPTIMAL
1.619 +// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
1.620 +// CPX_STAT_OPTIMAL_INFEAS
1.621 +// CPX_STAT_OPTIMAL_RELAXED
1.622 +// CPX_STAT_UNBOUNDED
1.623 +
1.624 + LpCplex::SolutionStatus LpCplex::_getDualStatus() const
1.625 + {
1.626 + int stat = CPXgetstat(env, lp);
1.627 +#if CPX_VERSION >= 800
1.628 + switch (stat)
1.629 + {
1.630 + case CPX_STAT_OPTIMAL:
1.631 + return OPTIMAL;
1.632 + case CPX_STAT_UNBOUNDED:
1.633 + return INFEASIBLE;
1.634 + default:
1.635 + return UNDEFINED;
1.636 + }
1.637 +#else
1.638 + statusSwitch(env,stat);
1.639 + switch (stat) {
1.640 + case 0:
1.641 + return UNDEFINED; //Undefined
1.642 + case CPX_OPTIMAL://Optimal
1.643 + return OPTIMAL;
1.644 + case CPX_UNBOUNDED:
1.645 + return INFEASIBLE;
1.646 + default:
1.647 + return UNDEFINED; //Everything else comes here
1.648 + //FIXME error
1.649 + }
1.650 +#endif
1.651 + }
1.652 +
1.653 + LpCplex::ProblemTypes LpCplex::_getProblemType() const
1.654 + {
1.655 + int stat = CPXgetstat(env, lp);
1.656 +#if CPX_VERSION >= 800
1.657 + switch (stat)
1.658 + {
1.659 + case CPX_STAT_OPTIMAL:
1.660 + return PRIMAL_DUAL_FEASIBLE;
1.661 + case CPX_STAT_UNBOUNDED:
1.662 + return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
1.663 + default:
1.664 + return UNKNOWN;
1.665 + }
1.666 +#else
1.667 + switch (stat) {
1.668 + case CPX_OPTIMAL://Optimal
1.669 + return PRIMAL_DUAL_FEASIBLE;
1.670 + case CPX_UNBOUNDED:
1.671 + return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
1.672 +// return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
1.673 +// return PRIMAL_DUAL_INFEASIBLE;
1.674 +
1.675 +//Seems to be that this is all we can say for sure
1.676 + default:
1.677 + //In all other cases
1.678 + return UNKNOWN;
1.679 + //FIXME error
1.680 + }
1.681 +#endif
1.682 + }
1.683 +
1.684 + void LpCplex::_setMax()
1.685 + {
1.686 + CPXchgobjsen(env, lp, CPX_MAX);
1.687 + }
1.688 + void LpCplex::_setMin()
1.689 + {
1.690 + CPXchgobjsen(env, lp, CPX_MIN);
1.691 + }
1.692 +
1.693 + bool LpCplex::_isMax() const
1.694 + {
1.695 + if (CPXgetobjsen(env, lp)==CPX_MAX)
1.696 + return true;
1.697 + else
1.698 + return false;
1.699 + }
1.700 +
1.701 +} //namespace lemon
1.702 +