lemon/lp_cplex.cc
changeset 2612 3d65053d01a3
parent 2591 3b4d5bc3b4fb
equal deleted inserted replaced
26:8c95c537e123 27:572eddd45411
    15  * purpose.
    15  * purpose.
    16  *
    16  *
    17  */
    17  */
    18 
    18 
    19 #include <iostream>
    19 #include <iostream>
       
    20 #include <vector>
    20 #include<lemon/lp_cplex.h>
    21 #include<lemon/lp_cplex.h>
    21 
    22 
    22 ///\file
    23 ///\file
    23 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
    24 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
    24 namespace lemon {
    25 namespace lemon {
    25   
    26   
    26   LpCplex::LpCplex() : LpSolverBase() {
    27   LpCplex::LpCplex() {
    27     //    env = CPXopenCPLEXdevelop(&status);     
    28     //    env = CPXopenCPLEXdevelop(&status);     
    28     env = CPXopenCPLEX(&status);     
    29     env = CPXopenCPLEX(&status);     
    29     lp = CPXcreateprob(env, &status, "LP problem");
    30     lp = CPXcreateprob(env, &status, "LP problem");
    30   }
    31   }
       
    32 
       
    33   LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
       
    34     env = CPXopenCPLEX(&status);     
       
    35     lp = CPXcloneprob(env, cplex.lp, &status);
       
    36     rows = cplex.rows;
       
    37     cols = cplex.cols;
       
    38   }
    31   
    39   
    32   LpCplex::~LpCplex() {
    40   LpCplex::~LpCplex() {
    33     CPXfreeprob(env,&lp); 
    41     CPXfreeprob(env,&lp);
    34     CPXcloseCPLEX(&env); 
    42     CPXcloseCPLEX(&env);
    35   }
    43   }
    36   
    44   
    37   LpSolverBase &LpCplex::_newLp() 
    45   LpSolverBase* LpCplex::_newLp() 
    38   {
    46   {
    39     //The first approach opens a new environment
    47     //The first approach opens a new environment
    40     LpCplex* newlp=new LpCplex();
    48     return new LpCplex();
    41     return *newlp;
    49   }
    42   }
    50 
    43 
    51   LpSolverBase* LpCplex::_copyLp() {
    44   LpSolverBase &LpCplex::_copyLp() {
    52     return new LpCplex(*this);
    45     ///\bug FixID data is not copied!
       
    46     //The first approach opens a new environment
       
    47     LpCplex* newlp=new LpCplex();
       
    48     //The routine CPXcloneprob can be used to create a new CPLEX problem 
       
    49     //object and copy all the problem data from an existing problem 
       
    50     //object to it. Solution and starting information is not copied.
       
    51     newlp->lp = CPXcloneprob(env, lp, &status);
       
    52     return *newlp;
       
    53   }
    53   }
    54 
    54 
    55   int LpCplex::_addCol()
    55   int LpCplex::_addCol()
    56   {
    56   {
    57     int i = CPXgetnumcols(env, lp);
    57     int i = CPXgetnumcols(env, lp);
    58     Value lb[1],ub[1];
    58     Value lb[1],ub[1];
    59     lb[0]=-INF;//-CPX_INFBOUND;
    59     lb[0]=-INF;
    60     ub[0]=INF;//CPX_INFBOUND;
    60     ub[0]=INF;
    61     status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
    61     status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
    62     return i;
    62     return i;
    63   }
    63   }
    64 
    64 
    65   
    65   
    87   void LpCplex::_getColName(int col, std::string &name) const
    87   void LpCplex::_getColName(int col, std::string &name) const
    88   {
    88   {
    89     ///\bug Untested
    89     ///\bug Untested
    90     int storespace;
    90     int storespace;
    91     CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
    91     CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
    92 
    92     if (storespace == 0) {
       
    93       name.clear();
       
    94       return;
       
    95     }
       
    96     
    93     storespace *= -1;
    97     storespace *= -1;
    94     std::vector<char> buf(storespace);
    98     std::vector<char> buf(storespace);
    95     char *names[1];
    99     char *names[1];
    96     int dontcare;
   100     int dontcare;
    97     ///\bug return code unchecked for error
   101     ///\bug return code unchecked for error
   134     status = CPXchgcoeflist(env, lp, values.size(), 
   138     status = CPXchgcoeflist(env, lp, values.size(), 
   135 			    &rowlist[0], &indices[0], &values[0]); 
   139 			    &rowlist[0], &indices[0], &values[0]); 
   136   }
   140   }
   137 
   141 
   138   void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
   142   void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
       
   143     int tmp1, tmp2, tmp3, length;
       
   144     CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
       
   145     
       
   146     length = -length;
       
   147     std::vector<int> indices(length);
       
   148     std::vector<double> values(length);
       
   149 
       
   150     CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 
       
   151 	       length, &tmp3, i, i);
       
   152     
       
   153     for (int i = 0; i < length; ++i) {
       
   154       *b = std::make_pair(indices[i], values[i]);
       
   155       ++b;
       
   156     }
       
   157     
   139     /// \todo implement
   158     /// \todo implement
   140   }
   159   }
   141   
   160   
   142   void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
   161   void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
   143   {
   162   {
   154     status = CPXchgcoeflist(env, lp, values.size(), 
   173     status = CPXchgcoeflist(env, lp, values.size(), 
   155 			    &indices[0], &collist[0], &values[0]); 
   174 			    &indices[0], &collist[0], &values[0]); 
   156   }
   175   }
   157 
   176 
   158   void LpCplex::_getColCoeffs(int i, ColIterator b) const {
   177   void LpCplex::_getColCoeffs(int i, ColIterator b) const {
   159     /// \todo implement
   178 
       
   179     int tmp1, tmp2, tmp3, length;
       
   180     CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
       
   181     
       
   182     length = -length;
       
   183     std::vector<int> indices(length);
       
   184     std::vector<double> values(length);
       
   185 
       
   186     CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0], 
       
   187 	       length, &tmp3, i, i);
       
   188     
       
   189     for (int i = 0; i < length; ++i) {
       
   190       *b = std::make_pair(indices[i], values[i]);
       
   191       ++b;
       
   192     }
       
   193     
   160   }
   194   }
   161   
   195   
   162   void LpCplex::_setCoeff(int row, int col, Value value) 
   196   void LpCplex::_setCoeff(int row, int col, Value value) 
   163   {
   197   {
   164     CPXchgcoef(env, lp, row, col, value);
   198     CPXchgcoef(env, lp, row, col, value);
   185 
   219 
   186   LpCplex::Value LpCplex::_getColLowerBound(int i) const
   220   LpCplex::Value LpCplex::_getColLowerBound(int i) const
   187   {
   221   {
   188     LpCplex::Value x;
   222     LpCplex::Value x;
   189     CPXgetlb (env, lp, &x, i, i);
   223     CPXgetlb (env, lp, &x, i, i);
       
   224     if (x <= -CPX_INFBOUND) x = -INF;
   190     return x;
   225     return x;
   191   }
   226   }
   192   
   227   
   193   void LpCplex::_setColUpperBound(int i, Value value)
   228   void LpCplex::_setColUpperBound(int i, Value value)
   194   {
   229   {
   203 
   238 
   204   LpCplex::Value LpCplex::_getColUpperBound(int i) const
   239   LpCplex::Value LpCplex::_getColUpperBound(int i) const
   205   {
   240   {
   206     LpCplex::Value x;
   241     LpCplex::Value x;
   207     CPXgetub (env, lp, &x, i, i);
   242     CPXgetub (env, lp, &x, i, i);
       
   243     if (x >= CPX_INFBOUND) x = INF;
   208     return x;
   244     return x;
   209   }
   245   }
   210 
   246 
   211   //This will be easier to implement
   247   //This will be easier to implement
   212   void LpCplex::_setRowBounds(int i, Value lb, Value ub)
   248   void LpCplex::_setRowBounds(int i, Value lb, Value ub)
   467 // 3 Network Simplex 
   503 // 3 Network Simplex 
   468 // 4 Standard Barrier 
   504 // 4 Standard Barrier 
   469 // Default: 0 
   505 // Default: 0 
   470 // Description: Method for linear optimization. 
   506 // Description: Method for linear optimization. 
   471 // Determines which algorithm is used when CPXlpopt() (or "optimize" in the Interactive Optimizer) is called. Currently the behavior of the "Automatic" setting is that CPLEX simply invokes the dual simplex method, but this capability may be expanded in the future so that CPLEX chooses the method based on problem characteristics 
   507 // Determines which algorithm is used when CPXlpopt() (or "optimize" in the Interactive Optimizer) is called. Currently the behavior of the "Automatic" setting is that CPLEX simply invokes the dual simplex method, but this capability may be expanded in the future so that CPLEX chooses the method based on problem characteristics 
       
   508 #if CPX_VERSION < 900
   472   void statusSwitch(CPXENVptr env,int& stat){
   509   void statusSwitch(CPXENVptr env,int& stat){
   473 #if CPX_VERSION < 900
       
   474     int lpmethod;
   510     int lpmethod;
   475     CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
   511     CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
   476     if (lpmethod==2){
   512     if (lpmethod==2){
   477       if (stat==CPX_UNBOUNDED){
   513       if (stat==CPX_UNBOUNDED){
   478 	stat=CPX_INFEASIBLE;
   514 	stat=CPX_INFEASIBLE;
   480       else{
   516       else{
   481 	if (stat==CPX_INFEASIBLE)
   517 	if (stat==CPX_INFEASIBLE)
   482 	  stat=CPX_UNBOUNDED;
   518 	  stat=CPX_UNBOUNDED;
   483       }
   519       }
   484     }
   520     }
       
   521   }
       
   522 #else
       
   523   void statusSwitch(CPXENVptr,int&){}
   485 #endif
   524 #endif
   486   }
       
   487 
   525 
   488   LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
   526   LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
   489   {
   527   {
   490     //Unboundedness not treated well: the following is from cplex 9.0 doc
   528     //Unboundedness not treated well: the following is from cplex 9.0 doc
   491     // About Unboundedness
   529     // About Unboundedness