COIN-OR::LEMON - Graph Library

Changeset 459:ed54c0d13df0 in lemon-1.2 for lemon/lp_cplex.cc


Ignore:
Timestamp:
12/02/08 22:48:28 (11 years ago)
Author:
Balazs Dezso <deba@…>
Branch:
default
Children:
460:76ec7bd57026, 502:17cabb114d52
Phase:
public
Message:

Thorough redesign of the LP/MIP interface (#44)

  • Redesigned class structure
  • Redesigned iterators
  • Some functions in the basic interface redesigned
  • More complete setting functions
  • Ray retrieving functions
  • Lot of improvements
  • Cplex common env
  • CLP macro definition to config.h.in
  • Update lp.h to also use soplex and clp
  • Remove default_solver_name
  • New solverName() function in solvers
  • Handle exceptions for MipCplex? test
  • Rename tolerance parameter to epsilon
  • Rename MapIt? to CoeffIt?
  • Lot of documentation improvements
  • Various bugfixes
File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/lp_cplex.cc

    r458 r459  
    1919#include <iostream>
    2020#include <vector>
     21#include <cstring>
     22
    2123#include <lemon/lp_cplex.h>
    2224
     
    3032namespace lemon {
    3133
    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);
    4187    rows = cplex.rows;
    4288    cols = cplex.cols;
    4389  }
    4490
    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);
    6799    return i;
    68100  }
    69101
    70102
    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);
    80108    return i;
    81109  }
    82110
    83111
    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) {
    98133      name.clear();
    99134      return;
    100135    }
    101136
    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 {
    123153    int index;
    124     if (CPXgetcolindex(env, lp,
     154    if (CPXgetcolindex(cplexEnv(), _prob,
    125155                       const_cast<char*>(name.c_str()), &index) == 0) {
    126156      return index;
     
    129159  }
    130160
    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)
    133195  {
    134196    std::vector<int> indices;
     
    136198    std::vector<Value> values;
    137199
    138     for(ConstRowIterator it=b; it!=e; ++it) {
     200    for(ExprIterator it=b; it!=e; ++it) {
    139201      indices.push_back(it->first);
    140202      values.push_back(it->second);
     
    142204    }
    143205
    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 {
    149211    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);
    151213
    152214    length = -length;
     
    154216    std::vector<double> values(length);
    155217
    156     CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
     218    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
     219               &indices.front(), &values.front(),
    157220               length, &tmp3, i, i);
    158221
     
    161224      ++b;
    162225    }
    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) {
    169229    std::vector<int> indices;
    170230    std::vector<int> collist;
    171231    std::vector<Value> values;
    172232
    173     for(ConstColIterator it=b; it!=e; ++it) {
     233    for(ExprIterator it=b; it!=e; ++it) {
    174234      indices.push_back(it->first);
    175235      values.push_back(it->second);
     
    177237    }
    178238
    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 {
    184244
    185245    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);
    187247
    188248    length = -length;
     
    190250    std::vector<double> values(length);
    191251
    192     CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
     252    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
     253               &indices.front(), &values.front(),
    193254               length, &tmp3, i, i);
    194255
     
    200261  }
    201262
    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)
    203285  {
    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)
    208359  {
    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)
    215365  {
    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)
    227372  {
    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
    235385  {
    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)
    246399  {
    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
    358404  {
    359405    Value x;
    360     CPXgetcoef(env, lp, -1, i, &x);
     406    CPXgetobj(cplexEnv(), _prob, &x, i, i);
    361407    return x;
    362408  }
    363409
    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
    371466  // The routine returns zero unless an error occurred during the
    372467  // optimization. Examples of errors include exhausting available
     
    378473  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
    379474  // 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) {
    385476#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 {
    388487      return UNSOLVED;
    389488    }
    390     else
    391     {
    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     }
    402489#else
    403     if (status == 0){
     490    if (status == 0) {
    404491      //We want to exclude some cases
    405       switch (CPXgetstat(env, lp)){
     492      switch (CPXgetstat(cplexEnv(), _prob)) {
    406493      case CPX_OBJ_LIM:
    407494      case CPX_IT_LIM_FEAS:
     
    413500        return SOLVED;
    414501      }
    415     }
    416     else{
     502    } else {
    417503      return UNSOLVED;
    418504    }
     
    420506  }
    421507
    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 {
    424529    Value x;
    425     CPXgetx(env, lp, &x, i, i);
     530    CPXgetx(cplexEnv(), _prob, &x, i, i);
    426531    return x;
    427532  }
    428533
    429   LpCplex::Value LpCplex::_getDual(int i) const
    430   {
     534  LpCplex::Value LpCplex::_getDual(int i) const {
    431535    Value y;
    432     CPXgetpi(env, lp, &y, i, i);
     536    CPXgetpi(cplexEnv(), _prob, &y, i, i);
    433537    return y;
    434538  }
    435539
    436   LpCplex::Value LpCplex::_getPrimalValue() const
    437   {
     540  LpCplex::Value LpCplex::_getPrimalValue() const {
    438541    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);
    443543    return objval;
    444544  }
    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
    520671#if CPX_VERSION < 900
    521   void statusSwitch(CPXENVptr env,int& stat){
     672  void statusSwitch(CPXENVptr cplexEnv(),int& stat){
    522673    int lpmethod;
    523     CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
     674    CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
    524675    if (lpmethod==2){
    525676      if (stat==CPX_UNBOUNDED){
     
    536687#endif
    537688
    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
    541691    // About Unboundedness
    542692
     
    553703    // has a feasible solution.
    554704
    555     int stat = CPXgetstat(env, lp);
     705    int stat = CPXgetstat(cplexEnv(), _prob);
    556706#if CPX_VERSION >= 800
    557707    switch (stat)
    558     {
     708      {
    559709      case CPX_STAT_OPTIMAL:
    560710        return OPTIMAL;
    561711      case CPX_STAT_UNBOUNDED:
    562         return INFINITE;
     712        return UNBOUNDED;
    563713      case CPX_STAT_INFEASIBLE:
    564714        return INFEASIBLE;
    565715      default:
    566716        return UNDEFINED;
    567     }
     717      }
    568718#else
    569     statusSwitch(env,stat);
    570     //CPXgetstat(env, lp);
     719    statusSwitch(cplexEnv(),stat);
     720    //CPXgetstat(cplexEnv(), _prob);
    571721    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
    572722    switch (stat) {
     
    577727    case CPX_UNBOUNDED://Unbounded
    578728      return INFEASIBLE;//In case of dual simplex
    579       //return INFINITE;
     729      //return UNBOUNDED;
    580730    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 simplex
     731      //    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
    589739      //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;
    597747    default:
    598748      return UNDEFINED; //Everything else comes here
     
    602752  }
    603753
    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);
    624773#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;
    633781    }
    634782#else
    635     statusSwitch(env,stat);
     783    statusSwitch(cplexEnv(),stat);
    636784    switch (stat) {
    637785    case 0:
     
    640788      return OPTIMAL;
    641789    case CPX_UNBOUNDED:
    642      return INFEASIBLE;
     790      return INFEASIBLE;
    643791    default:
    644792      return UNDEFINED; //Everything else comes here
     
    648796  }
    649797
    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);
    663805#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
    664881    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;
    696922  }
    697923
Note: See TracChangeset for help on using the changeset viewer.