lemon/cplex.cc
changeset 473 17d918051964
parent 461 08d495d48089
child 540 9db62975c32b
equal deleted inserted replaced
0:c4781ecf069b 1:6cc1635c5623
   436     _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
   436     _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
   437     rows.clear();
   437     rows.clear();
   438     cols.clear();
   438     cols.clear();
   439   }
   439   }
   440 
   440 
   441   // LpCplex members
   441   // CplexLp members
   442 
   442 
   443   LpCplex::LpCplex()
   443   CplexLp::CplexLp()
   444     : LpBase(), CplexBase(), LpSolver() {}
   444     : LpBase(), CplexBase(), LpSolver() {}
   445 
   445 
   446   LpCplex::LpCplex(const CplexEnv& env)
   446   CplexLp::CplexLp(const CplexEnv& env)
   447     : LpBase(), CplexBase(env), LpSolver() {}
   447     : LpBase(), CplexBase(env), LpSolver() {}
   448 
   448 
   449   LpCplex::LpCplex(const LpCplex& other)
   449   CplexLp::CplexLp(const CplexLp& other)
   450     : LpBase(), CplexBase(other), LpSolver() {}
   450     : LpBase(), CplexBase(other), LpSolver() {}
   451 
   451 
   452   LpCplex::~LpCplex() {}
   452   CplexLp::~CplexLp() {}
   453 
   453 
   454   LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
   454   CplexLp* CplexLp::_newSolver() const { return new CplexLp; }
   455   LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
   455   CplexLp* CplexLp::_cloneSolver() const {return new CplexLp(*this); }
   456 
   456 
   457   const char* LpCplex::_solverName() const { return "LpCplex"; }
   457   const char* CplexLp::_solverName() const { return "CplexLp"; }
   458 
   458 
   459   void LpCplex::_clear_temporals() {
   459   void CplexLp::_clear_temporals() {
   460     _col_status.clear();
   460     _col_status.clear();
   461     _row_status.clear();
   461     _row_status.clear();
   462     _primal_ray.clear();
   462     _primal_ray.clear();
   463     _dual_ray.clear();
   463     _dual_ray.clear();
   464   }
   464   }
   470   // user-specified CPLEX limit, or proving the model infeasible or
   470   // user-specified CPLEX limit, or proving the model infeasible or
   471   // unbounded, are not considered errors. Note that a zero return
   471   // unbounded, are not considered errors. Note that a zero return
   472   // value does not necessarily mean that a solution exists. Use query
   472   // value does not necessarily mean that a solution exists. Use query
   473   // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
   473   // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
   474   // further information about the status of the optimization.
   474   // further information about the status of the optimization.
   475   LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
   475   CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
   476 #if CPX_VERSION >= 800
   476 #if CPX_VERSION >= 800
   477     if (status == 0) {
   477     if (status == 0) {
   478       switch (CPXgetstat(cplexEnv(), _prob)) {
   478       switch (CPXgetstat(cplexEnv(), _prob)) {
   479       case CPX_STAT_OPTIMAL:
   479       case CPX_STAT_OPTIMAL:
   480       case CPX_STAT_INFEASIBLE:
   480       case CPX_STAT_INFEASIBLE:
   503       return UNSOLVED;
   503       return UNSOLVED;
   504     }
   504     }
   505 #endif
   505 #endif
   506   }
   506   }
   507 
   507 
   508   LpCplex::SolveExitStatus LpCplex::_solve() {
   508   CplexLp::SolveExitStatus CplexLp::_solve() {
   509     _clear_temporals();
   509     _clear_temporals();
   510     return convertStatus(CPXlpopt(cplexEnv(), _prob));
   510     return convertStatus(CPXlpopt(cplexEnv(), _prob));
   511   }
   511   }
   512 
   512 
   513   LpCplex::SolveExitStatus LpCplex::solvePrimal() {
   513   CplexLp::SolveExitStatus CplexLp::solvePrimal() {
   514     _clear_temporals();
   514     _clear_temporals();
   515     return convertStatus(CPXprimopt(cplexEnv(), _prob));
   515     return convertStatus(CPXprimopt(cplexEnv(), _prob));
   516   }
   516   }
   517 
   517 
   518   LpCplex::SolveExitStatus LpCplex::solveDual() {
   518   CplexLp::SolveExitStatus CplexLp::solveDual() {
   519     _clear_temporals();
   519     _clear_temporals();
   520     return convertStatus(CPXdualopt(cplexEnv(), _prob));
   520     return convertStatus(CPXdualopt(cplexEnv(), _prob));
   521   }
   521   }
   522 
   522 
   523   LpCplex::SolveExitStatus LpCplex::solveBarrier() {
   523   CplexLp::SolveExitStatus CplexLp::solveBarrier() {
   524     _clear_temporals();
   524     _clear_temporals();
   525     return convertStatus(CPXbaropt(cplexEnv(), _prob));
   525     return convertStatus(CPXbaropt(cplexEnv(), _prob));
   526   }
   526   }
   527 
   527 
   528   LpCplex::Value LpCplex::_getPrimal(int i) const {
   528   CplexLp::Value CplexLp::_getPrimal(int i) const {
   529     Value x;
   529     Value x;
   530     CPXgetx(cplexEnv(), _prob, &x, i, i);
   530     CPXgetx(cplexEnv(), _prob, &x, i, i);
   531     return x;
   531     return x;
   532   }
   532   }
   533 
   533 
   534   LpCplex::Value LpCplex::_getDual(int i) const {
   534   CplexLp::Value CplexLp::_getDual(int i) const {
   535     Value y;
   535     Value y;
   536     CPXgetpi(cplexEnv(), _prob, &y, i, i);
   536     CPXgetpi(cplexEnv(), _prob, &y, i, i);
   537     return y;
   537     return y;
   538   }
   538   }
   539 
   539 
   540   LpCplex::Value LpCplex::_getPrimalValue() const {
   540   CplexLp::Value CplexLp::_getPrimalValue() const {
   541     Value objval;
   541     Value objval;
   542     CPXgetobjval(cplexEnv(), _prob, &objval);
   542     CPXgetobjval(cplexEnv(), _prob, &objval);
   543     return objval;
   543     return objval;
   544   }
   544   }
   545 
   545 
   546   LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
   546   CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
   547     if (_col_status.empty()) {
   547     if (_col_status.empty()) {
   548       _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
   548       _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
   549       CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
   549       CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
   550     }
   550     }
   551     switch (_col_status[i]) {
   551     switch (_col_status[i]) {
   557       return LOWER;
   557       return LOWER;
   558     case CPX_AT_UPPER:
   558     case CPX_AT_UPPER:
   559       return UPPER;
   559       return UPPER;
   560     default:
   560     default:
   561       LEMON_ASSERT(false, "Wrong column status");
   561       LEMON_ASSERT(false, "Wrong column status");
   562       return LpCplex::VarStatus();
   562       return CplexLp::VarStatus();
   563     }
   563     }
   564   }
   564   }
   565 
   565 
   566   LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
   566   CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
   567     if (_row_status.empty()) {
   567     if (_row_status.empty()) {
   568       _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
   568       _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
   569       CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
   569       CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
   570     }
   570     }
   571     switch (_row_status[i]) {
   571     switch (_row_status[i]) {
   579       }
   579       }
   580     case CPX_AT_UPPER:
   580     case CPX_AT_UPPER:
   581       return UPPER;
   581       return UPPER;
   582     default:
   582     default:
   583       LEMON_ASSERT(false, "Wrong row status");
   583       LEMON_ASSERT(false, "Wrong row status");
   584       return LpCplex::VarStatus();
   584       return CplexLp::VarStatus();
   585     }
   585     }
   586   }
   586   }
   587 
   587 
   588   LpCplex::Value LpCplex::_getPrimalRay(int i) const {
   588   CplexLp::Value CplexLp::_getPrimalRay(int i) const {
   589     if (_primal_ray.empty()) {
   589     if (_primal_ray.empty()) {
   590       _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
   590       _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
   591       CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
   591       CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
   592     }
   592     }
   593     return _primal_ray[i];
   593     return _primal_ray[i];
   594   }
   594   }
   595 
   595 
   596   LpCplex::Value LpCplex::_getDualRay(int i) const {
   596   CplexLp::Value CplexLp::_getDualRay(int i) const {
   597     if (_dual_ray.empty()) {
   597     if (_dual_ray.empty()) {
   598 
   598 
   599     }
   599     }
   600     return _dual_ray[i];
   600     return _dual_ray[i];
   601   }
   601   }
   684   }
   684   }
   685 #else
   685 #else
   686   void statusSwitch(CPXENVptr,int&){}
   686   void statusSwitch(CPXENVptr,int&){}
   687 #endif
   687 #endif
   688 
   688 
   689   LpCplex::ProblemType LpCplex::_getPrimalType() const {
   689   CplexLp::ProblemType CplexLp::_getPrimalType() const {
   690     // Unboundedness not treated well: the following is from cplex 9.0 doc
   690     // Unboundedness not treated well: the following is from cplex 9.0 doc
   691     // About Unboundedness
   691     // About Unboundedness
   692 
   692 
   693     // The treatment of models that are unbounded involves a few
   693     // The treatment of models that are unbounded involves a few
   694     // subtleties. Specifically, a declaration of unboundedness means that
   694     // subtleties. Specifically, a declaration of unboundedness means that
   766   // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
   766   // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
   767   // CPX_STAT_OPTIMAL_INFEAS
   767   // CPX_STAT_OPTIMAL_INFEAS
   768   // CPX_STAT_OPTIMAL_RELAXED
   768   // CPX_STAT_OPTIMAL_RELAXED
   769   // CPX_STAT_UNBOUNDED
   769   // CPX_STAT_UNBOUNDED
   770 
   770 
   771   LpCplex::ProblemType LpCplex::_getDualType() const {
   771   CplexLp::ProblemType CplexLp::_getDualType() const {
   772     int stat = CPXgetstat(cplexEnv(), _prob);
   772     int stat = CPXgetstat(cplexEnv(), _prob);
   773 #if CPX_VERSION >= 800
   773 #if CPX_VERSION >= 800
   774     switch (stat) {
   774     switch (stat) {
   775     case CPX_STAT_OPTIMAL:
   775     case CPX_STAT_OPTIMAL:
   776       return OPTIMAL;
   776       return OPTIMAL;
   793       //FIXME error
   793       //FIXME error
   794     }
   794     }
   795 #endif
   795 #endif
   796   }
   796   }
   797 
   797 
   798   // MipCplex members
   798   // CplexMip members
   799 
   799 
   800   MipCplex::MipCplex()
   800   CplexMip::CplexMip()
   801     : LpBase(), CplexBase(), MipSolver() {
   801     : LpBase(), CplexBase(), MipSolver() {
   802 
   802 
   803 #if CPX_VERSION < 800
   803 #if CPX_VERSION < 800
   804     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
   804     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
   805 #else
   805 #else
   806     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
   806     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
   807 #endif
   807 #endif
   808   }
   808   }
   809 
   809 
   810   MipCplex::MipCplex(const CplexEnv& env)
   810   CplexMip::CplexMip(const CplexEnv& env)
   811     : LpBase(), CplexBase(env), MipSolver() {
   811     : LpBase(), CplexBase(env), MipSolver() {
   812 
   812 
   813 #if CPX_VERSION < 800
   813 #if CPX_VERSION < 800
   814     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
   814     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
   815 #else
   815 #else
   816     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
   816     CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
   817 #endif
   817 #endif
   818 
   818 
   819   }
   819   }
   820 
   820 
   821   MipCplex::MipCplex(const MipCplex& other)
   821   CplexMip::CplexMip(const CplexMip& other)
   822     : LpBase(), CplexBase(other), MipSolver() {}
   822     : LpBase(), CplexBase(other), MipSolver() {}
   823 
   823 
   824   MipCplex::~MipCplex() {}
   824   CplexMip::~CplexMip() {}
   825 
   825 
   826   MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
   826   CplexMip* CplexMip::_newSolver() const { return new CplexMip; }
   827   MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
   827   CplexMip* CplexMip::_cloneSolver() const {return new CplexMip(*this); }
   828 
   828 
   829   const char* MipCplex::_solverName() const { return "MipCplex"; }
   829   const char* CplexMip::_solverName() const { return "CplexMip"; }
   830 
   830 
   831   void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
   831   void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
   832 
   832 
   833     // Note If a variable is to be changed to binary, a call to CPXchgbds
   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.
   834     // should also be made to change the bounds to 0 and 1.
   835 
   835 
   836     switch (col_type){
   836     switch (col_type){
   845     default:
   845     default:
   846       break;
   846       break;
   847     }
   847     }
   848   }
   848   }
   849 
   849 
   850   MipCplex::ColTypes MipCplex::_getColType(int i) const {
   850   CplexMip::ColTypes CplexMip::_getColType(int i) const {
   851     char t;
   851     char t;
   852     CPXgetctype (cplexEnv(), _prob, &t, i, i);
   852     CPXgetctype (cplexEnv(), _prob, &t, i, i);
   853     switch (t) {
   853     switch (t) {
   854     case 'I':
   854     case 'I':
   855       return INTEGER;
   855       return INTEGER;
   860       return ColTypes();
   860       return ColTypes();
   861     }
   861     }
   862 
   862 
   863   }
   863   }
   864 
   864 
   865   MipCplex::SolveExitStatus MipCplex::_solve() {
   865   CplexMip::SolveExitStatus CplexMip::_solve() {
   866     int status;
   866     int status;
   867     status = CPXmipopt (cplexEnv(), _prob);
   867     status = CPXmipopt (cplexEnv(), _prob);
   868     if (status==0)
   868     if (status==0)
   869       return SOLVED;
   869       return SOLVED;
   870     else
   870     else
   871       return UNSOLVED;
   871       return UNSOLVED;
   872 
   872 
   873   }
   873   }
   874 
   874 
   875 
   875 
   876   MipCplex::ProblemType MipCplex::_getType() const {
   876   CplexMip::ProblemType CplexMip::_getType() const {
   877 
   877 
   878     int stat = CPXgetstat(cplexEnv(), _prob);
   878     int stat = CPXgetstat(cplexEnv(), _prob);
   879 
   879 
   880     //Fortunately, MIP statuses did not change for cplex 8.0
   880     //Fortunately, MIP statuses did not change for cplex 8.0
   881     switch (stat) {
   881     switch (stat) {
   907     // a feasible solution exists. Users can call the routine CPXsolninfo
   907     // a feasible solution exists. Users can call the routine CPXsolninfo
   908     // to determine whether ILOG CPLEX has also concluded that the model
   908     // to determine whether ILOG CPLEX has also concluded that the model
   909     // has a feasible solution.
   909     // has a feasible solution.
   910   }
   910   }
   911 
   911 
   912   MipCplex::Value MipCplex::_getSol(int i) const {
   912   CplexMip::Value CplexMip::_getSol(int i) const {
   913     Value x;
   913     Value x;
   914     CPXgetmipx(cplexEnv(), _prob, &x, i, i);
   914     CPXgetmipx(cplexEnv(), _prob, &x, i, i);
   915     return x;
   915     return x;
   916   }
   916   }
   917 
   917 
   918   MipCplex::Value MipCplex::_getSolValue() const {
   918   CplexMip::Value CplexMip::_getSolValue() const {
   919     Value objval;
   919     Value objval;
   920     CPXgetmipobjval(cplexEnv(), _prob, &objval);
   920     CPXgetmipobjval(cplexEnv(), _prob, &objval);
   921     return objval;
   921     return objval;
   922   }
   922   }
   923 
   923