lemon/lp_cplex.cc
author alpar
Thu, 09 Jun 2005 09:49:56 +0000
changeset 1459 2ee881cf30a8
parent 1436 e0beb94d08bf
child 1460 7c58aabb9eea
permissions -rw-r--r--
- InDegMap fixed
- OutDegMap added
- test cases added for them both
     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 
   264 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
   265 // 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.
   266 
   267 // For Simplex, Barrier  
   268 // 1  	CPX_OPTIMAL  
   269 // 	 Optimal solution found  
   270 // 2  	CPX_INFEASIBLE  
   271 // 	 Problem infeasible  
   272 // 3    CPX_UNBOUNDED  
   273 // 	 Problem unbounded  
   274 // 4  	CPX_OBJ_LIM  
   275 // 	 Objective limit exceeded in Phase II  
   276 // 5  	CPX_IT_LIM_FEAS  
   277 // 	 Iteration limit exceeded in Phase II  
   278 // 6  	CPX_IT_LIM_INFEAS  
   279 // 	 Iteration limit exceeded in Phase I  
   280 // 7  	CPX_TIME_LIM_FEAS  
   281 // 	 Time limit exceeded in Phase II  
   282 // 8  	CPX_TIME_LIM_INFEAS  
   283 // 	 Time limit exceeded in Phase I  
   284 // 9  	CPX_NUM_BEST_FEAS  
   285 // 	 Problem non-optimal, singularities in Phase II  
   286 // 10 	CPX_NUM_BEST_INFEAS  
   287 // 	 Problem non-optimal, singularities in Phase I  
   288 // 11 	CPX_OPTIMAL_INFEAS  
   289 // 	 Optimal solution found, unscaled infeasibilities  
   290 // 12 	CPX_ABORT_FEAS  
   291 // 	 Aborted in Phase II  
   292 // 13 	CPX_ABORT_INFEAS  
   293 // 	 Aborted in Phase I  
   294 // 14  	CPX_ABORT_DUAL_INFEAS  
   295 // 	 Aborted in barrier, dual infeasible  
   296 // 15  	CPX_ABORT_PRIM_INFEAS  
   297 // 	 Aborted in barrier, primal infeasible  
   298 // 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
   299 // 	 Aborted in barrier, primal and dual infeasible  
   300 // 17  	CPX_ABORT_PRIM_DUAL_FEAS  
   301 // 	 Aborted in barrier, primal and dual feasible  
   302 // 18  	CPX_ABORT_CROSSOVER  
   303 // 	 Aborted in crossover  
   304 // 19  	CPX_INForUNBD  
   305 // 	 Infeasible or unbounded  
   306 // 20   CPX_PIVOT
   307 //       User pivot used
   308 //
   309 //     Ezeket hova tegyem:
   310 // ??case CPX_ABORT_DUAL_INFEAS           
   311 // ??case CPX_ABORT_CROSSOVER             
   312 // ??case CPX_INForUNBD                   
   313 // ??case CPX_PIVOT                       
   314 
   315   LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
   316   {
   317     int stat = CPXgetstat (env, lp);
   318     switch (stat) {
   319     case 0:
   320       return UNDEFINED; //Undefined
   321     case CPX_OPTIMAL://Optimal
   322       return OPTIMAL;
   323     case CPX_UNBOUNDED://Unbounded
   324       return INFINITE;
   325     case CPX_INFEASIBLE://Infeasible 
   326  //    case CPX_IT_LIM_INFEAS:
   327 //     case CPX_TIME_LIM_INFEAS:
   328 //     case CPX_NUM_BEST_INFEAS:             
   329 //     case CPX_OPTIMAL_INFEAS:              
   330 //     case CPX_ABORT_INFEAS:                
   331 //     case CPX_ABORT_PRIM_INFEAS:           
   332 //     case CPX_ABORT_PRIM_DUAL_INFEAS:      
   333       return INFEASIBLE;
   334 //     case CPX_OBJ_LIM:                    
   335 //     case CPX_IT_LIM_FEAS:             
   336 //     case CPX_TIME_LIM_FEAS:                
   337 //     case CPX_NUM_BEST_FEAS:                
   338 //     case CPX_ABORT_FEAS:                  
   339 //     case CPX_ABORT_PRIM_DUAL_FEAS:        
   340 //       return FEASIBLE;
   341     default:
   342       return UNDEFINED; //Everything else comes here
   343       //FIXME error
   344     }
   345 
   346   }
   347 
   348 //9.0-as cplex verzio statusai
   349 // CPX_STAT_ABORT_DUAL_OBJ_LIM
   350 // CPX_STAT_ABORT_IT_LIM
   351 // CPX_STAT_ABORT_OBJ_LIM
   352 // CPX_STAT_ABORT_PRIM_OBJ_LIM
   353 // CPX_STAT_ABORT_TIME_LIM
   354 // CPX_STAT_ABORT_USER
   355 // CPX_STAT_FEASIBLE_RELAXED
   356 // CPX_STAT_INFEASIBLE
   357 // CPX_STAT_INForUNBD
   358 // CPX_STAT_NUM_BEST
   359 // CPX_STAT_OPTIMAL
   360 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
   361 // CPX_STAT_OPTIMAL_INFEAS
   362 // CPX_STAT_OPTIMAL_RELAXED
   363 // CPX_STAT_UNBOUNDED
   364 
   365   LpCplex::SolutionStatus LpCplex::_getDualStatus()
   366   {
   367     int stat = CPXgetstat (env, lp);
   368     switch (stat) {
   369     case 0:
   370       return UNDEFINED; //Undefined
   371     case CPX_OPTIMAL://Optimal
   372       return OPTIMAL;
   373     case CPX_UNBOUNDED:
   374      return INFEASIBLE;
   375     default:
   376       return UNDEFINED; //Everything else comes here
   377       //FIXME error
   378     }
   379 
   380   LpCplex::Value LpCplex::_getPrimal(int i)
   381   {
   382     Value x;
   383     CPXgetx (env, lp, &x, i, i);
   384     return x;
   385   }
   386   
   387   LpCplex::Value LpCplex::_getPrimalValue()
   388   {
   389     Value objval;
   390     //method = CPXgetmethod (env, lp);
   391     status = CPXgetobjval (env, lp, &objval);
   392     return objval;
   393   }
   394   
   395  
   396 
   397 
   398   void LpCplex::_setMax()
   399   {
   400     CPXchgobjsen (env, lp, CPX_MAX);
   401    }
   402   void LpCplex::_setMin()
   403   {
   404     CPXchgobjsen (env, lp, CPX_MIN);
   405    }
   406   
   407 } //namespace lemon
   408