src/lemon/lp_glpk.cc
changeset 1435 8e85e6bbefdf
parent 1431 ad44b1dd8013
equal deleted inserted replaced
13:014cc517c831 -1:000000000000
     1 /* -*- C++ -*-
       
     2  * src/lemon/lp_glpk.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 
       
    17 #ifndef LEMON_LP_GLPK_CC
       
    18 #define LEMON_LP_GLPK_CC
       
    19 
       
    20 ///\file
       
    21 ///\brief Implementation of the LEMON-GLPK lp solver interface.
       
    22 
       
    23 #include <lemon/lp_glpk.h>
       
    24 
       
    25 namespace lemon {
       
    26 
       
    27   ///\e
       
    28 
       
    29   ///\bug Unimplemented!
       
    30   ///
       
    31   LpSolverBase &LpGlpk::_newLp()
       
    32   {
       
    33     LpSolverBase *tmp=0;
       
    34     return *tmp;
       
    35   }
       
    36   
       
    37   ///\e
       
    38 
       
    39   ///\bug Unimplemented!
       
    40   ///
       
    41   LpSolverBase &LpGlpk::_copyLp()
       
    42   {
       
    43     LpSolverBase *tmp=0;
       
    44     return *tmp;
       
    45   }
       
    46 
       
    47   LpGlpk::LpGlpk() : Parent(), 
       
    48 		     lp(lpx_create_prob()) {
       
    49     ///\todo constrol function for this:
       
    50     lpx_set_int_parm(lp, LPX_K_DUAL, 1);
       
    51     messageLevel(0);
       
    52   }
       
    53   
       
    54   LpGlpk::~LpGlpk() {
       
    55     lpx_delete_prob(lp);
       
    56   }
       
    57   
       
    58   int LpGlpk::_addCol() { 
       
    59     int i=lpx_add_cols(lp, 1);
       
    60     _setColLowerBound(i, -INF);
       
    61     _setColUpperBound(i, INF);
       
    62     return i;
       
    63   }
       
    64 
       
    65   int LpGlpk::_addRow() { 
       
    66     int i=lpx_add_rows(lp, 1);
       
    67     return i;
       
    68   }
       
    69 
       
    70   
       
    71   void LpGlpk::_eraseCol(int i) {
       
    72     int cols[2];
       
    73     cols[1]=i;
       
    74     lpx_del_cols(lp, 1, cols);
       
    75   }
       
    76   
       
    77   void LpGlpk::_eraseRow(int i) {
       
    78     int rows[2];
       
    79     rows[1]=i;
       
    80     lpx_del_rows(lp, 1, rows);
       
    81   }
       
    82 
       
    83   void LpGlpk::_setRowCoeffs(int i, 
       
    84 			     int length,
       
    85 			     const int   * indices, 
       
    86 			     const Value   * values )
       
    87   {
       
    88     lpx_set_mat_row(lp, i, length,
       
    89 		    const_cast<int * >(indices) ,
       
    90 		    const_cast<Value * >(values));
       
    91   }
       
    92   
       
    93   void LpGlpk::_setColCoeffs(int i, 
       
    94 			     int length,
       
    95 			     const int   * indices, 
       
    96 			     const Value   * values)
       
    97   {
       
    98     lpx_set_mat_col(lp, i, length,
       
    99 		    const_cast<int * >(indices),
       
   100 		    const_cast<Value * >(values));
       
   101   }
       
   102 
       
   103 
       
   104   void LpGlpk::_setCoeff(int row, int col, Value value) 
       
   105   {
       
   106     ///FIXME Of course this is not efficient at all, but GLPK knows not more.
       
   107     // First approach: get one row, apply changes and set it again
       
   108     //(one idea to improve this: maybe it is better to do this with 1 coloumn)
       
   109     
       
   110     int mem_length=2+lpx_get_num_cols(lp);
       
   111     int* indices = new int[mem_length];
       
   112     Value* values = new Value[mem_length];
       
   113     
       
   114 
       
   115     int length=lpx_get_mat_row(lp, row, indices, values);
       
   116 
       
   117     //The following code does not suppose that the elements of the array indices are sorted
       
   118     int i=1;
       
   119     bool found=false;
       
   120     while (i <= length && !found){
       
   121       if (indices[i]==col){
       
   122 	found = true;
       
   123 	values[i]=value;
       
   124       }
       
   125       ++i;
       
   126     }
       
   127     if (!found){
       
   128       ++length;
       
   129       indices[length]=col;
       
   130       values[length]=value;
       
   131     }
       
   132     
       
   133     lpx_set_mat_row(lp, row, length, indices, values);
       
   134     delete [] indices;
       
   135     delete [] values;
       
   136     
       
   137   }
       
   138 
       
   139   void LpGlpk::_setColLowerBound(int i, Value lo)
       
   140   {
       
   141     if (lo==INF) {
       
   142       //FIXME error
       
   143     }
       
   144     int b=lpx_get_col_type(lp, i);
       
   145     double up=lpx_get_col_ub(lp, i);	
       
   146     if (lo==-INF) {
       
   147       switch (b) {
       
   148       case LPX_FR:
       
   149       case LPX_LO:
       
   150 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
       
   151 	break;
       
   152       case LPX_UP:
       
   153 	break;
       
   154       case LPX_DB:
       
   155       case LPX_FX:
       
   156 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
       
   157 	break;
       
   158       default: ;
       
   159 	//FIXME error
       
   160       }
       
   161     } else {
       
   162       switch (b) {
       
   163       case LPX_FR:
       
   164       case LPX_LO:
       
   165 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
       
   166 	break;
       
   167       case LPX_UP:	  
       
   168       case LPX_DB:
       
   169       case LPX_FX:
       
   170 	if (lo==up) 
       
   171 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
       
   172 	else 
       
   173 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
       
   174 	break;
       
   175       default: ;
       
   176 	//FIXME error
       
   177       }
       
   178     }
       
   179 
       
   180   }
       
   181   
       
   182   void LpGlpk::_setColUpperBound(int i, Value up)
       
   183   {
       
   184     if (up==-INF) {
       
   185       //FIXME error
       
   186     }
       
   187     int b=lpx_get_col_type(lp, i);
       
   188     double lo=lpx_get_col_lb(lp, i);
       
   189     if (up==INF) {
       
   190       switch (b) {
       
   191       case LPX_FR:
       
   192       case LPX_LO:
       
   193 	break;
       
   194       case LPX_UP:
       
   195 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
       
   196 	break;
       
   197       case LPX_DB:
       
   198       case LPX_FX:
       
   199 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
       
   200 	break;
       
   201       default: ;
       
   202 	//FIXME error
       
   203       }
       
   204     } else {
       
   205       switch (b) {
       
   206       case LPX_FR:
       
   207 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
       
   208 	break;
       
   209       case LPX_UP:
       
   210 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
       
   211 	break;
       
   212       case LPX_LO:
       
   213       case LPX_DB:
       
   214       case LPX_FX:
       
   215 	if (lo==up) 
       
   216 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
       
   217 	else 
       
   218 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
       
   219 	break;
       
   220       default: ;
       
   221 	//FIXME error
       
   222       }
       
   223     }
       
   224   }
       
   225   
       
   226 //   void LpGlpk::_setRowLowerBound(int i, Value lo)
       
   227 //   {
       
   228 //     if (lo==INF) {
       
   229 //       //FIXME error
       
   230 //     }
       
   231 //     int b=lpx_get_row_type(lp, i);
       
   232 //     double up=lpx_get_row_ub(lp, i);	
       
   233 //     if (lo==-INF) {
       
   234 //       switch (b) {
       
   235 //       case LPX_FR:
       
   236 //       case LPX_LO:
       
   237 // 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
       
   238 // 	break;
       
   239 //       case LPX_UP:
       
   240 // 	break;
       
   241 //       case LPX_DB:
       
   242 //       case LPX_FX:
       
   243 // 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
       
   244 // 	break;
       
   245 //       default: ;
       
   246 // 	//FIXME error
       
   247 //       }
       
   248 //     } else {
       
   249 //       switch (b) {
       
   250 //       case LPX_FR:
       
   251 //       case LPX_LO:
       
   252 // 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
       
   253 // 	break;
       
   254 //       case LPX_UP:	  
       
   255 //       case LPX_DB:
       
   256 //       case LPX_FX:
       
   257 // 	if (lo==up) 
       
   258 // 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
       
   259 // 	else 
       
   260 // 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
       
   261 // 	break;
       
   262 //       default: ;
       
   263 // 	//FIXME error
       
   264 //       }
       
   265 //     }
       
   266 //   }
       
   267   
       
   268 //   void LpGlpk::_setRowUpperBound(int i, Value up)
       
   269 //   {
       
   270 //     if (up==-INF) {
       
   271 //       //FIXME error
       
   272 //     }
       
   273 //     int b=lpx_get_row_type(lp, i);
       
   274 //     double lo=lpx_get_row_lb(lp, i);
       
   275 //     if (up==INF) {
       
   276 //       switch (b) {
       
   277 //       case LPX_FR:
       
   278 //       case LPX_LO:
       
   279 // 	break;
       
   280 //       case LPX_UP:
       
   281 // 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
       
   282 // 	break;
       
   283 //       case LPX_DB:
       
   284 //       case LPX_FX:
       
   285 // 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
       
   286 // 	break;
       
   287 //       default: ;
       
   288 // 	//FIXME error
       
   289 //       }
       
   290 //     } else {
       
   291 //       switch (b) {
       
   292 //       case LPX_FR:
       
   293 // 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
       
   294 // 	break;
       
   295 //       case LPX_UP:
       
   296 // 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
       
   297 // 	break;
       
   298 //       case LPX_LO:
       
   299 //       case LPX_DB:
       
   300 //       case LPX_FX:
       
   301 // 	if (lo==up) 
       
   302 // 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
       
   303 // 	else 
       
   304 // 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
       
   305 // 	break;
       
   306 //       default: ;
       
   307 // 	//FIXME error
       
   308 //       }
       
   309 //     }
       
   310 //   }
       
   311 
       
   312   void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
       
   313   {
       
   314     //Bad parameter
       
   315     if (lb==INF || ub==-INF) {
       
   316       //FIXME error
       
   317     }
       
   318 
       
   319     if (lb == -INF){
       
   320       if (ub == INF){
       
   321 	lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
       
   322       }
       
   323       else{
       
   324 	lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
       
   325       }
       
   326     }
       
   327     else{
       
   328       if (ub==INF){
       
   329 	lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
       
   330 
       
   331       }
       
   332       else{
       
   333 	if (lb == ub){
       
   334 	  lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
       
   335 	}
       
   336 	else{
       
   337 	  lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
       
   338 	}
       
   339       }
       
   340     }
       
   341 
       
   342   }
       
   343   
       
   344   void LpGlpk::_setObjCoeff(int i, Value obj_coef)
       
   345   {
       
   346     //i=0 means the constant term (shift)
       
   347     lpx_set_obj_coef(lp, i, obj_coef);
       
   348   }
       
   349 
       
   350   void LpGlpk::_clearObj()
       
   351   {
       
   352     for (int i=0;i<=lpx_get_num_cols(lp);++i){
       
   353       lpx_set_obj_coef(lp, i, 0);
       
   354     }
       
   355   }
       
   356 //   void LpGlpk::_setObj(int length,
       
   357 // 		       int  const * indices, 
       
   358 // 		       Value  const * values )
       
   359 //   {
       
   360 //     Value new_values[1+lpx_num_cols()];
       
   361 //     for (i=0;i<=lpx_num_cols();++i){
       
   362 //       new_values[i]=0;
       
   363 //     }
       
   364 //     for (i=1;i<=length;++i){
       
   365 //       new_values[indices[i]]=values[i];
       
   366 //     }
       
   367     
       
   368 //     for (i=0;i<=lpx_num_cols();++i){
       
   369 //       lpx_set_obj_coef(lp, i, new_values[i]);
       
   370 //     }
       
   371 //   }
       
   372 
       
   373   LpGlpk::SolveExitStatus LpGlpk::_solve()
       
   374   {
       
   375     int i=  lpx_simplex(lp);
       
   376     switch (i) {
       
   377     case LPX_E_OK: 
       
   378       return SOLVED;
       
   379       break;
       
   380     default:
       
   381       return UNSOLVED;
       
   382     }
       
   383   }
       
   384 
       
   385   LpGlpk::Value LpGlpk::_getPrimal(int i)
       
   386   {
       
   387     return lpx_get_col_prim(lp,i);
       
   388   }
       
   389   
       
   390   LpGlpk::Value LpGlpk::_getPrimalValue()
       
   391   {
       
   392     return lpx_get_obj_val(lp);
       
   393   }
       
   394   
       
   395  
       
   396   LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
       
   397   {
       
   398     int stat=  lpx_get_status(lp);
       
   399     switch (stat) {
       
   400     case LPX_UNDEF://Undefined (no solve has been run yet)
       
   401       return UNDEFINED;
       
   402       break;
       
   403     case LPX_NOFEAS://There is no feasible solution (primal, I guess)
       
   404     case LPX_INFEAS://Infeasible 
       
   405       return INFEASIBLE;
       
   406       break;
       
   407     case LPX_UNBND://Unbounded
       
   408       return INFINITE;
       
   409       break;
       
   410     case LPX_FEAS://Feasible
       
   411       return FEASIBLE;
       
   412       break;
       
   413     case LPX_OPT://Feasible
       
   414       return OPTIMAL;
       
   415       break;
       
   416     default:
       
   417       return UNDEFINED; //to avoid gcc warning
       
   418       //FIXME error
       
   419     }
       
   420   }
       
   421 
       
   422 
       
   423   void LpGlpk::_setMax()
       
   424   {
       
   425     lpx_set_obj_dir(lp, LPX_MAX);
       
   426   }
       
   427 
       
   428   void LpGlpk::_setMin()
       
   429   {
       
   430     lpx_set_obj_dir(lp, LPX_MIN);
       
   431   }
       
   432 
       
   433  
       
   434   void LpGlpk::messageLevel(int m)
       
   435   {
       
   436     lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
       
   437   }
       
   438 
       
   439   void LpGlpk::presolver(bool b)
       
   440   {
       
   441     lpx_set_int_parm(lp, LPX_K_PRESOL, b);
       
   442   }
       
   443 
       
   444  
       
   445 } //END OF NAMESPACE LEMON
       
   446 
       
   447 #endif //LEMON_LP_GLPK_CC