lemon/lp_cplex.cc
author ladanyi
Tue, 14 Jun 2005 22:51:22 +0000
changeset 1490 fa2b73784343
parent 1460 7c58aabb9eea
child 1508 389a94a1d9eb
permissions -rw-r--r--
Added support for building deb packages.
     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     status = CPXgetobjval (env, lp, &objval);
   275     return objval;
   276   }
   277   
   278 
   279 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
   280 // 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.
   281 
   282 // For Simplex, Barrier  
   283 // 1  	CPX_OPTIMAL  
   284 // 	 Optimal solution found  
   285 // 2  	CPX_INFEASIBLE  
   286 // 	 Problem infeasible  
   287 // 3    CPX_UNBOUNDED  
   288 // 	 Problem unbounded  
   289 // 4  	CPX_OBJ_LIM  
   290 // 	 Objective limit exceeded in Phase II  
   291 // 5  	CPX_IT_LIM_FEAS  
   292 // 	 Iteration limit exceeded in Phase II  
   293 // 6  	CPX_IT_LIM_INFEAS  
   294 // 	 Iteration limit exceeded in Phase I  
   295 // 7  	CPX_TIME_LIM_FEAS  
   296 // 	 Time limit exceeded in Phase II  
   297 // 8  	CPX_TIME_LIM_INFEAS  
   298 // 	 Time limit exceeded in Phase I  
   299 // 9  	CPX_NUM_BEST_FEAS  
   300 // 	 Problem non-optimal, singularities in Phase II  
   301 // 10 	CPX_NUM_BEST_INFEAS  
   302 // 	 Problem non-optimal, singularities in Phase I  
   303 // 11 	CPX_OPTIMAL_INFEAS  
   304 // 	 Optimal solution found, unscaled infeasibilities  
   305 // 12 	CPX_ABORT_FEAS  
   306 // 	 Aborted in Phase II  
   307 // 13 	CPX_ABORT_INFEAS  
   308 // 	 Aborted in Phase I  
   309 // 14  	CPX_ABORT_DUAL_INFEAS  
   310 // 	 Aborted in barrier, dual infeasible  
   311 // 15  	CPX_ABORT_PRIM_INFEAS  
   312 // 	 Aborted in barrier, primal infeasible  
   313 // 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
   314 // 	 Aborted in barrier, primal and dual infeasible  
   315 // 17  	CPX_ABORT_PRIM_DUAL_FEAS  
   316 // 	 Aborted in barrier, primal and dual feasible  
   317 // 18  	CPX_ABORT_CROSSOVER  
   318 // 	 Aborted in crossover  
   319 // 19  	CPX_INForUNBD  
   320 // 	 Infeasible or unbounded  
   321 // 20   CPX_PIVOT
   322 //       User pivot used
   323 //
   324 //     Ezeket hova tegyem:
   325 // ??case CPX_ABORT_DUAL_INFEAS           
   326 // ??case CPX_ABORT_CROSSOVER             
   327 // ??case CPX_INForUNBD                   
   328 // ??case CPX_PIVOT                       
   329 
   330   LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
   331   {
   332     int stat = CPXgetstat (env, lp);
   333     switch (stat) {
   334     case 0:
   335       return UNDEFINED; //Undefined
   336     case CPX_OPTIMAL://Optimal
   337       return OPTIMAL;
   338     case CPX_UNBOUNDED://Unbounded
   339       return INFINITE;
   340     case CPX_INFEASIBLE://Infeasible 
   341  //    case CPX_IT_LIM_INFEAS:
   342 //     case CPX_TIME_LIM_INFEAS:
   343 //     case CPX_NUM_BEST_INFEAS:             
   344 //     case CPX_OPTIMAL_INFEAS:              
   345 //     case CPX_ABORT_INFEAS:                
   346 //     case CPX_ABORT_PRIM_INFEAS:           
   347 //     case CPX_ABORT_PRIM_DUAL_INFEAS:      
   348       return INFEASIBLE;
   349 //     case CPX_OBJ_LIM:                    
   350 //     case CPX_IT_LIM_FEAS:             
   351 //     case CPX_TIME_LIM_FEAS:                
   352 //     case CPX_NUM_BEST_FEAS:                
   353 //     case CPX_ABORT_FEAS:                  
   354 //     case CPX_ABORT_PRIM_DUAL_FEAS:        
   355 //       return FEASIBLE;
   356     default:
   357       return UNDEFINED; //Everything else comes here
   358       //FIXME error
   359     }
   360 
   361   }
   362 
   363 //9.0-as cplex verzio statusai
   364 // CPX_STAT_ABORT_DUAL_OBJ_LIM
   365 // CPX_STAT_ABORT_IT_LIM
   366 // CPX_STAT_ABORT_OBJ_LIM
   367 // CPX_STAT_ABORT_PRIM_OBJ_LIM
   368 // CPX_STAT_ABORT_TIME_LIM
   369 // CPX_STAT_ABORT_USER
   370 // CPX_STAT_FEASIBLE_RELAXED
   371 // CPX_STAT_INFEASIBLE
   372 // CPX_STAT_INForUNBD
   373 // CPX_STAT_NUM_BEST
   374 // CPX_STAT_OPTIMAL
   375 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
   376 // CPX_STAT_OPTIMAL_INFEAS
   377 // CPX_STAT_OPTIMAL_RELAXED
   378 // CPX_STAT_UNBOUNDED
   379 
   380   LpCplex::SolutionStatus LpCplex::_getDualStatus()
   381   {
   382     int stat = CPXgetstat (env, lp);
   383     switch (stat) {
   384     case 0:
   385       return UNDEFINED; //Undefined
   386     case CPX_OPTIMAL://Optimal
   387       return OPTIMAL;
   388     case CPX_UNBOUNDED:
   389      return INFEASIBLE;
   390     default:
   391       return UNDEFINED; //Everything else comes here
   392       //FIXME error
   393     }
   394   }
   395 
   396   LpCplex::ProblemTypes LpCplex::_getProblemType()
   397   {
   398     int stat = CPXgetstat (env, lp);
   399     switch (stat) {
   400     case CPX_OPTIMAL://Optimal
   401 	return PRIMAL_DUAL_FEASIBLE;
   402     case CPX_UNBOUNDED:
   403  	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   404 // 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
   405 // 	return PRIMAL_DUAL_INFEASIBLE;
   406 
   407 //Seems to be that this is all we can say for sure
   408     default:
   409 	//In all other cases
   410 	return UNKNOWN;
   411       //FIXME error
   412     }
   413   }
   414 
   415   void LpCplex::_setMax()
   416   {
   417     CPXchgobjsen (env, lp, CPX_MAX);
   418    }
   419   void LpCplex::_setMin()
   420   {
   421     CPXchgobjsen (env, lp, CPX_MIN);
   422    }
   423   
   424 } //namespace lemon
   425