lemon/lp_cplex.cc
author alpar
Wed, 29 Jun 2005 12:52:20 +0000
changeset 1523 144ab0e4b09c
parent 1473 876c7b7f4dae
child 1542 0219ee65ffcc
permissions -rw-r--r--
Hmmm...
     1 /* -*- C++ -*-
     2  * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 #include <iostream>
    17 #include<lemon/lp_cplex.h>
    18 
    19 ///\file
    20 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
    21 namespace lemon {
    22   
    23   LpCplex::LpCplex() : LpSolverBase() {
    24 
    25     //    env = CPXopenCPLEXdevelop(&status);     
    26     env = CPXopenCPLEX(&status);     
    27     lp = CPXcreateprob(env, &status, "LP problem");
    28   }
    29   
    30   LpCplex::~LpCplex() {
    31     CPXfreeprob(env,&lp); 
    32     CPXcloseCPLEX(&env); 
    33   }
    34   
    35   LpSolverBase &LpCplex::_newLp() 
    36   {
    37     //The first approach opens a new environment
    38     LpCplex* newlp=new LpCplex();
    39     return *newlp;
    40   }
    41 
    42   LpSolverBase &LpCplex::_copyLp() {
    43     //The first approach opens a new environment
    44     LpCplex* newlp=new LpCplex();
    45     //The routine CPXcloneprob can be used to create a new CPLEX problem 
    46     //object and copy all the problem data from an existing problem 
    47     //object to it. Solution and starting information is not copied.
    48     newlp->lp = CPXcloneprob(env, lp, &status);
    49     return *newlp;
    50   }
    51 
    52   int LpCplex::_addCol()
    53   {
    54     int i = CPXgetnumcols(env, lp);
    55     Value lb[1],ub[1];
    56     lb[0]=-INF;//-CPX_INFBOUND;
    57     ub[0]=INF;//CPX_INFBOUND;
    58     status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
    59     return i;
    60   }
    61 
    62   
    63   int LpCplex::_addRow() 
    64   {
    65     //We want a row that is not constrained
    66     char sense[1];
    67     sense[0]='L';//<= constraint
    68     Value rhs[1];
    69     rhs[0]=INF;
    70     int i = CPXgetnumrows(env, lp);
    71     status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
    72     return i;
    73   }
    74 
    75 
    76   void LpCplex::_eraseCol(int i) {
    77     CPXdelcols(env, lp, i, i);
    78   }
    79   
    80   void LpCplex::_eraseRow(int i) {
    81     CPXdelrows(env, lp, i, i);
    82   }
    83 
    84   
    85   ///\warning Data at index 0 is ignored in the arrays.
    86   void LpCplex::_setRowCoeffs(int i, 
    87 			      int length,
    88 			      int  const * indices, 
    89 			      Value  const * values )
    90   {
    91     int rowlist[length+1];
    92     int* p=rowlist;
    93     for (int k=1;k<=length;++k){
    94       rowlist[k]=i;
    95     }
    96     status = CPXchgcoeflist(env, lp, 
    97 			    length, 
    98 			    p+1, 
    99 			    const_cast<int * >(indices+1), 
   100 			    const_cast<Value * >(values+1));
   101   }
   102   
   103   void LpCplex::_setColCoeffs(int i, 
   104 			      int length,
   105 			      int  const * indices, 
   106 			      Value  const * values)
   107   {
   108     int collist[length+1];
   109     int* p=collist;
   110     for (int k=1;k<=length;++k){
   111       collist[k]=i;
   112     }
   113     status = CPXchgcoeflist(env, lp, 
   114 			    length, 
   115 			    const_cast<int * >(indices+1), 
   116 			    p+1, 
   117 			    const_cast<Value * >(values+1));
   118   }
   119   
   120   void LpCplex::_setCoeff(int row, int col, Value value) 
   121   {
   122     CPXchgcoef(env, lp, row, col, value);
   123   }
   124 
   125   void LpCplex::_setColLowerBound(int i, Value value)
   126   {
   127     int indices[1];
   128     indices[0]=i;
   129     char lu[1];
   130     lu[0]='L';
   131     Value bd[1];
   132     bd[0]=value;
   133     status = CPXchgbds(env, lp, 1, indices, lu, bd);
   134  
   135   }
   136   
   137   void LpCplex::_setColUpperBound(int i, Value value)
   138   {
   139     int indices[1];
   140     indices[0]=i;
   141     char lu[1];
   142     lu[0]='U';
   143     Value bd[1];
   144     bd[0]=value;
   145     status = CPXchgbds(env, lp, 1, indices, lu, bd);
   146   }
   147 
   148   //This will be easier to implement
   149   void LpCplex::_setRowBounds(int i, Value lb, Value ub)
   150   {
   151     //Bad parameter
   152     if (lb==INF || ub==-INF) {
   153       //FIXME error
   154     }
   155     
   156     int cnt=1;
   157     int indices[1];
   158     indices[0]=i;
   159     char sense[1];
   160 
   161     if (lb==-INF){
   162       sense[0]='L';
   163       CPXchgsense(env, lp, cnt, indices, sense);
   164       CPXchgcoef(env, lp, i, -1, ub);
   165       
   166     }
   167     else{
   168       if (ub==INF){
   169 	sense[0]='G';
   170 	CPXchgsense(env, lp, cnt, indices, sense);
   171 	CPXchgcoef(env, lp, i, -1, lb);
   172       }
   173       else{
   174 	if (lb == ub){
   175 	  sense[0]='E';
   176 	  CPXchgsense(env, lp, cnt, indices, sense);
   177 	  CPXchgcoef(env, lp, i, -1, lb);
   178 	}
   179 	else{
   180 	  sense[0]='R';
   181 	  CPXchgsense(env, lp, cnt, indices, sense);
   182 	  CPXchgcoef(env, lp, i, -1, lb);
   183 	  CPXchgcoef(env, lp, i, -2, ub-lb);	  
   184 	}
   185       }
   186     }
   187   }
   188 
   189 //   void LpCplex::_setRowLowerBound(int i, Value value)
   190 //   {
   191 //     //Not implemented, obsolete
   192 //   }
   193   
   194 //   void LpCplex::_setRowUpperBound(int i, Value value)
   195 //   {
   196 //     //Not implemented, obsolete
   197 // //     //TODO Ezt kell meg megirni
   198 // //     //type of the problem
   199 // //     char sense[1];
   200 // //     status = CPXgetsense(env, lp, sense, i, i);
   201 // //     Value rhs[1];
   202 // //     status = CPXgetrhs(env, lp, rhs, i, i);
   203 
   204 // //     switch (sense[0]) {
   205 // //     case 'L'://<= constraint
   206 // //       break;
   207 // //     case 'E'://= constraint
   208 // //       break;
   209 // //     case 'G'://>= constraint
   210 // //       break;
   211 // //     case 'R'://ranged constraint
   212 // //       break;
   213 // //     default: ;
   214 // //       //FIXME error
   215 // //     }
   216 
   217 // //     status = CPXchgcoef(env, lp, i, -2, value_rng);
   218 //   }
   219   
   220   void LpCplex::_setObjCoeff(int i, Value obj_coef)
   221   {
   222     CPXchgcoef(env, lp, -1, i, obj_coef);
   223   }
   224 
   225   void LpCplex::_clearObj()
   226   {
   227     for (int i=0;i< CPXgetnumcols(env, lp);++i){
   228       CPXchgcoef(env, lp, -1, i, 0);
   229     }
   230     
   231   }
   232   // The routine returns zero unless an error occurred during the
   233   // optimization. Examples of errors include exhausting available
   234   // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
   235   // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
   236   // user-specified CPLEX limit, or proving the model infeasible or
   237   // unbounded, are not considered errors. Note that a zero return
   238   // value does not necessarily mean that a solution exists. Use query
   239   // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
   240   // further information about the status of the optimization.
   241   LpCplex::SolveExitStatus LpCplex::_solve()
   242   {
   243     //CPX_PARAM_LPMETHOD 
   244     status = CPXlpopt(env, lp);
   245     if (status == 0){
   246       //We want to exclude some cases
   247       switch (CPXgetstat(env, lp)){
   248       case CPX_OBJ_LIM:
   249       case CPX_IT_LIM_FEAS:
   250       case CPX_IT_LIM_INFEAS:               
   251       case CPX_TIME_LIM_FEAS:
   252       case CPX_TIME_LIM_INFEAS:
   253 	return UNSOLVED;
   254       default:
   255 	return SOLVED; 
   256       }
   257     }
   258     else{
   259       return UNSOLVED;
   260     }
   261   }
   262 
   263   LpCplex::Value LpCplex::_getPrimal(int i)
   264   {
   265     Value x;
   266     CPXgetx(env, lp, &x, i, i);
   267     return x;
   268   }
   269   
   270   LpCplex::Value LpCplex::_getPrimalValue()
   271   {
   272     Value objval;
   273     //method = CPXgetmethod (env, lp);
   274     //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
   275     status = CPXgetobjval(env, lp, &objval);
   276     //printf("Objective value: %g \n",objval);
   277     return objval;
   278   }
   279   
   280 
   281 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
   282 // This table lists the statuses, returned by the CPXgetstat() routine, for solutions to LP problems or mixed integer problems. If no solution exists, the return value is zero.
   283 
   284 // For Simplex, Barrier  
   285 // 1  	CPX_OPTIMAL  
   286 // 	 Optimal solution found  
   287 // 2  	CPX_INFEASIBLE  
   288 // 	 Problem infeasible  
   289 // 3    CPX_UNBOUNDED  
   290 // 	 Problem unbounded  
   291 // 4  	CPX_OBJ_LIM  
   292 // 	 Objective limit exceeded in Phase II  
   293 // 5  	CPX_IT_LIM_FEAS  
   294 // 	 Iteration limit exceeded in Phase II  
   295 // 6  	CPX_IT_LIM_INFEAS  
   296 // 	 Iteration limit exceeded in Phase I  
   297 // 7  	CPX_TIME_LIM_FEAS  
   298 // 	 Time limit exceeded in Phase II  
   299 // 8  	CPX_TIME_LIM_INFEAS  
   300 // 	 Time limit exceeded in Phase I  
   301 // 9  	CPX_NUM_BEST_FEAS  
   302 // 	 Problem non-optimal, singularities in Phase II  
   303 // 10 	CPX_NUM_BEST_INFEAS  
   304 // 	 Problem non-optimal, singularities in Phase I  
   305 // 11 	CPX_OPTIMAL_INFEAS  
   306 // 	 Optimal solution found, unscaled infeasibilities  
   307 // 12 	CPX_ABORT_FEAS  
   308 // 	 Aborted in Phase II  
   309 // 13 	CPX_ABORT_INFEAS  
   310 // 	 Aborted in Phase I  
   311 // 14  	CPX_ABORT_DUAL_INFEAS  
   312 // 	 Aborted in barrier, dual infeasible  
   313 // 15  	CPX_ABORT_PRIM_INFEAS  
   314 // 	 Aborted in barrier, primal infeasible  
   315 // 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
   316 // 	 Aborted in barrier, primal and dual infeasible  
   317 // 17  	CPX_ABORT_PRIM_DUAL_FEAS  
   318 // 	 Aborted in barrier, primal and dual feasible  
   319 // 18  	CPX_ABORT_CROSSOVER  
   320 // 	 Aborted in crossover  
   321 // 19  	CPX_INForUNBD  
   322 // 	 Infeasible or unbounded  
   323 // 20   CPX_PIVOT
   324 //       User pivot used
   325 //
   326 //     Ezeket hova tegyem:
   327 // ??case CPX_ABORT_DUAL_INFEAS           
   328 // ??case CPX_ABORT_CROSSOVER             
   329 // ??case CPX_INForUNBD                   
   330 // ??case CPX_PIVOT                       
   331 
   332   LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
   333   {
   334     int stat = CPXgetstat(env, lp);
   335     //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
   336     switch (stat) {
   337     case 0:
   338       return UNDEFINED; //Undefined
   339     case CPX_OPTIMAL://Optimal
   340       return OPTIMAL;
   341     case CPX_UNBOUNDED://Unbounded
   342       return INFINITE;
   343     case CPX_INFEASIBLE://Infeasible 
   344  //    case CPX_IT_LIM_INFEAS:
   345 //     case CPX_TIME_LIM_INFEAS:
   346 //     case CPX_NUM_BEST_INFEAS:             
   347 //     case CPX_OPTIMAL_INFEAS:              
   348 //     case CPX_ABORT_INFEAS:                
   349 //     case CPX_ABORT_PRIM_INFEAS:           
   350 //     case CPX_ABORT_PRIM_DUAL_INFEAS:      
   351       return INFEASIBLE;
   352 //     case CPX_OBJ_LIM:                    
   353 //     case CPX_IT_LIM_FEAS:             
   354 //     case CPX_TIME_LIM_FEAS:                
   355 //     case CPX_NUM_BEST_FEAS:                
   356 //     case CPX_ABORT_FEAS:                  
   357 //     case CPX_ABORT_PRIM_DUAL_FEAS:        
   358 //       return FEASIBLE;
   359     default:
   360       return UNDEFINED; //Everything else comes here
   361       //FIXME error
   362     }
   363 
   364   }
   365 
   366 //9.0-as cplex verzio statusai
   367 // CPX_STAT_ABORT_DUAL_OBJ_LIM
   368 // CPX_STAT_ABORT_IT_LIM
   369 // CPX_STAT_ABORT_OBJ_LIM
   370 // CPX_STAT_ABORT_PRIM_OBJ_LIM
   371 // CPX_STAT_ABORT_TIME_LIM
   372 // CPX_STAT_ABORT_USER
   373 // CPX_STAT_FEASIBLE_RELAXED
   374 // CPX_STAT_INFEASIBLE
   375 // CPX_STAT_INForUNBD
   376 // CPX_STAT_NUM_BEST
   377 // CPX_STAT_OPTIMAL
   378 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
   379 // CPX_STAT_OPTIMAL_INFEAS
   380 // CPX_STAT_OPTIMAL_RELAXED
   381 // CPX_STAT_UNBOUNDED
   382 
   383   LpCplex::SolutionStatus LpCplex::_getDualStatus()
   384   {
   385     int stat = CPXgetstat(env, lp);
   386     switch (stat) {
   387     case 0:
   388       return UNDEFINED; //Undefined
   389     case CPX_OPTIMAL://Optimal
   390       return OPTIMAL;
   391     case CPX_UNBOUNDED:
   392      return INFEASIBLE;
   393     default:
   394       return UNDEFINED; //Everything else comes here
   395       //FIXME error
   396     }
   397   }
   398 
   399   LpCplex::ProblemTypes LpCplex::_getProblemType()
   400   {
   401     int stat = CPXgetstat(env, lp);
   402     switch (stat) {
   403     case CPX_OPTIMAL://Optimal
   404 	return PRIMAL_DUAL_FEASIBLE;
   405     case CPX_UNBOUNDED:
   406  	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   407 // 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
   408 // 	return PRIMAL_DUAL_INFEASIBLE;
   409 
   410 //Seems to be that this is all we can say for sure
   411     default:
   412 	//In all other cases
   413 	return UNKNOWN;
   414       //FIXME error
   415     }
   416   }
   417 
   418   void LpCplex::_setMax()
   419   {
   420     CPXchgobjsen(env, lp, CPX_MAX);
   421    }
   422   void LpCplex::_setMin()
   423   {
   424     CPXchgobjsen(env, lp, CPX_MIN);
   425    }
   426   
   427 } //namespace lemon
   428