lemon/lp_glpk.cc
author deba
Thu, 15 Feb 2007 14:22:08 +0000
changeset 2363 2aabce558574
parent 2349 c945f577a66d
child 2364 3a5e67bd42d2
permissions -rw-r--r--
Changes on the LP interface

_FixId => LpId
- handling of not common ids // soplex
LpGlpk row and col erase bug fix
- calling lpx_std_basis before simplex
LpSoplex
- added getter functions
- better m4 file
- integration to the tests
- better handling of unsolved lps
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 ///\file
    20 ///\brief Implementation of the LEMON-GLPK lp solver interface.
    21 
    22 #include <lemon/lp_glpk.h>
    23 //#include <iostream>
    24 namespace lemon {
    25 
    26 
    27   LpGlpk::LpGlpk() : Parent() {
    28     rows = _lp_bits::LpId(1);
    29     cols = _lp_bits::LpId(1);
    30     lp = lpx_create_prob();
    31     ///\todo control function for this:
    32     lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    33     messageLevel(0);
    34   }
    35   
    36   LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
    37     rows = _lp_bits::LpId(1);
    38     cols = _lp_bits::LpId(1);
    39     lp = lpx_create_prob();
    40     ///\todo control function for this:
    41     lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    42     messageLevel(0);
    43     //Coefficient matrix, row bounds
    44     lpx_add_rows(lp, lpx_get_num_rows(glp.lp));
    45     lpx_add_cols(lp, lpx_get_num_cols(glp.lp));
    46     int len;
    47     int ind[1+lpx_get_num_cols(glp.lp)];
    48     Value val[1+lpx_get_num_cols(glp.lp)];
    49     for (int i=1;i<=lpx_get_num_rows(glp.lp);++i)
    50       {
    51 	len=lpx_get_mat_row(glp.lp,i,ind,val);
    52 	lpx_set_mat_row(lp, i,len,ind,val);
    53 	lpx_set_row_bnds(lp,i,lpx_get_row_type(glp.lp,i),
    54 			 lpx_get_row_lb(glp.lp,i),lpx_get_row_ub(glp.lp,i));
    55       }
    56 
    57     //Objective function, coloumn bounds
    58     lpx_set_obj_dir(lp, lpx_get_obj_dir(glp.lp));
    59     //Objectif function's constant term treated separately
    60     lpx_set_obj_coef(lp,0,lpx_get_obj_coef(glp.lp,0));
    61     for (int i=1;i<=lpx_get_num_cols(glp.lp);++i)
    62       {
    63 	lpx_set_obj_coef(lp,i,lpx_get_obj_coef(glp.lp,i));
    64 	lpx_set_col_bnds(lp,i,lpx_get_col_type(glp.lp,i),
    65 			 lpx_get_col_lb(glp.lp,i),lpx_get_col_ub(glp.lp,i));
    66       }
    67   }
    68   
    69   LpGlpk::~LpGlpk() {
    70     lpx_delete_prob(lp);
    71   }
    72   
    73   int LpGlpk::_addCol() { 
    74     int i=lpx_add_cols(lp, 1);
    75     _setColLowerBound(i, -INF);
    76     _setColUpperBound(i, INF);
    77     return i;
    78   }
    79 
    80   ///\e
    81 
    82 
    83   LpSolverBase &LpGlpk::_newLp()
    84   {
    85     LpGlpk* newlp=new LpGlpk;
    86     return *newlp;
    87   }
    88   
    89   ///\e
    90 
    91   LpSolverBase &LpGlpk::_copyLp()
    92   {
    93     LpGlpk* newlp=new LpGlpk(*this);
    94     return *newlp;
    95   }
    96 
    97   int LpGlpk::_addRow() { 
    98     int i=lpx_add_rows(lp, 1);
    99     return i;
   100   }
   101 
   102   
   103   void LpGlpk::_eraseCol(int i) {
   104     int cols[2];
   105     cols[1]=i;
   106     lpx_del_cols(lp, 1, cols);
   107   }
   108   
   109   void LpGlpk::_eraseRow(int i) {
   110     int rows[2];
   111     rows[1]=i;
   112     lpx_del_rows(lp, 1, rows);
   113   }
   114 
   115   void LpGlpk::_getColName(int col, std::string & name)
   116   {
   117     
   118     char *n = lpx_get_col_name(lp,col);
   119     name = n?n:"";
   120   }
   121   
   122   
   123   void LpGlpk::_setColName(int col, const std::string & name)
   124   {
   125     lpx_set_col_name(lp,col,const_cast<char*>(name.c_str()));
   126 
   127   }
   128   
   129   void LpGlpk::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e) 
   130   {
   131     std::vector<int> indices;
   132     std::vector<Value> values;
   133 
   134     indices.push_back(0);
   135     values.push_back(0);
   136 
   137     for(LpRowIterator it=b; it!=e; ++it) {
   138       indices.push_back(it->first);
   139       values.push_back(it->second);
   140     }
   141 
   142     lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
   143   }
   144   
   145   void LpGlpk::_setColCoeffs(int i, LpColIterator b, LpColIterator e) {
   146 
   147     std::vector<int> indices;
   148     std::vector<Value> values;
   149 
   150     indices.push_back(0);
   151     values.push_back(0);
   152 
   153     for(LpColIterator it=b; it!=e; ++it) {
   154       indices.push_back(it->first);
   155       values.push_back(it->second);
   156     }
   157     
   158     lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]);
   159   }
   160 
   161 
   162   void LpGlpk::_setCoeff(int row, int col, Value value) 
   163   {
   164 
   165     if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
   166 
   167       int length=lpx_get_mat_row(lp, row, 0, 0);
   168       
   169       std::vector<int> indices(length + 2);
   170       std::vector<Value> values(length + 2);
   171       
   172       lpx_get_mat_row(lp, row, &indices[0], &values[0]);
   173       
   174       //The following code does not suppose that the elements of the
   175       //array indices are sorted
   176       bool found=false;
   177       for (int i = 1; i <= length; ++i) {
   178         if (indices[i]==col){
   179           found=true;
   180           values[i]=value;
   181           break;
   182         }
   183       }
   184       if (!found){
   185         ++length;
   186         indices[length]=col;
   187         values[length]=value;
   188       }
   189     
   190       lpx_set_mat_row(lp, row, length, &indices[0], &values[0]);
   191 
   192     } else {
   193 
   194       int length=lpx_get_mat_col(lp, col, 0, 0);
   195       
   196       std::vector<int> indices(length + 2);
   197       std::vector<Value> values(length + 2);
   198       
   199       lpx_get_mat_col(lp, col, &indices[0], &values[0]);
   200       
   201       //The following code does not suppose that the elements of the
   202       //array indices are sorted
   203       bool found=false;
   204       for (int i = 1; i <= length; ++i) {
   205         if (indices[i]==col){
   206           found=true;
   207           values[i]=value;
   208           break;
   209         }
   210       }
   211       if (!found){
   212         ++length;
   213         indices[length]=row;
   214         values[length]=value;
   215       }
   216     
   217       lpx_set_mat_col(lp, col, length, &indices[0], &values[0]);
   218     }
   219   }
   220 
   221   LpGlpk::Value LpGlpk::_getCoeff(int row, int col)
   222   {
   223 
   224     int length=lpx_get_mat_row(lp, row, 0, 0);
   225     
   226     std::vector<int> indices(length + 2);
   227     std::vector<Value> values(length + 2);
   228     
   229     lpx_get_mat_row(lp, row, &indices[0], &values[0]);
   230     
   231     //The following code does not suppose that the elements of the
   232     //array indices are sorted
   233     for (int i = 1; i <= length; ++i) {
   234       if (indices[i]==col){
   235 	return values[i];
   236       }
   237     }
   238     return 0;
   239 
   240   }
   241 
   242 
   243   void LpGlpk::_setColLowerBound(int i, Value lo)
   244   {
   245     if (lo==INF) {
   246       //FIXME error
   247     }
   248     int b=lpx_get_col_type(lp, i);
   249     double up=lpx_get_col_ub(lp, i);	
   250     if (lo==-INF) {
   251       switch (b) {
   252       case LPX_FR:
   253       case LPX_LO:
   254 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   255 	break;
   256       case LPX_UP:
   257 	break;
   258       case LPX_DB:
   259       case LPX_FX:
   260 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   261 	break;
   262       default: ;
   263 	//FIXME error
   264       }
   265     } else {
   266       switch (b) {
   267       case LPX_FR:
   268       case LPX_LO:
   269 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   270 	break;
   271       case LPX_UP:	  
   272       case LPX_DB:
   273       case LPX_FX:
   274 	if (lo==up) 
   275 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   276 	else 
   277 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   278 	break;
   279       default: ;
   280 	//FIXME error
   281       }
   282     }
   283 
   284   }
   285 
   286   LpGlpk::Value LpGlpk::_getColLowerBound(int i)
   287   {
   288     int b=lpx_get_col_type(lp, i);
   289       switch (b) {
   290       case LPX_LO:
   291       case LPX_DB:
   292       case LPX_FX:
   293 	return lpx_get_col_lb(lp, i);	
   294       default: ;
   295 	return -INF;
   296       }
   297   }
   298   
   299   void LpGlpk::_setColUpperBound(int i, Value up)
   300   {
   301     if (up==-INF) {
   302       //FIXME error
   303     }
   304     int b=lpx_get_col_type(lp, i);
   305     double lo=lpx_get_col_lb(lp, i);
   306     if (up==INF) {
   307       switch (b) {
   308       case LPX_FR:
   309       case LPX_LO:
   310 	break;
   311       case LPX_UP:
   312 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   313 	break;
   314       case LPX_DB:
   315       case LPX_FX:
   316 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   317 	break;
   318       default: ;
   319 	//FIXME error
   320       }
   321     } else {
   322       switch (b) {
   323       case LPX_FR:
   324 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   325 	break;
   326       case LPX_UP:
   327 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   328 	break;
   329       case LPX_LO:
   330       case LPX_DB:
   331       case LPX_FX:
   332 	if (lo==up) 
   333 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   334 	else 
   335 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   336 	break;
   337       default: ;
   338 	//FIXME error
   339       }
   340     }
   341   }
   342 
   343   LpGlpk::Value LpGlpk::_getColUpperBound(int i)
   344   {
   345     int b=lpx_get_col_type(lp, i);
   346       switch (b) {
   347       case LPX_UP:
   348       case LPX_DB:
   349       case LPX_FX:
   350 	return lpx_get_col_ub(lp, i);	
   351       default: ;
   352 	return INF;
   353       }
   354   }
   355   
   356   void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
   357   {
   358     //Bad parameter
   359     if (lb==INF || ub==-INF) {
   360       //FIXME error
   361     }
   362 
   363     if (lb == -INF){
   364       if (ub == INF){
   365 	lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
   366       }
   367       else{
   368 	lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
   369       }
   370     }
   371     else{
   372       if (ub==INF){
   373 	lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
   374 
   375       }
   376       else{
   377 	if (lb == ub){
   378 	  lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
   379 	}
   380 	else{
   381 	  lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
   382 	}
   383       }
   384     }
   385 
   386   }
   387 
   388   void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub)
   389   {
   390 
   391     int b=lpx_get_row_type(lp, i);
   392     switch (b) {
   393     case LPX_FR:
   394     case LPX_UP:
   395       lb = -INF;
   396 	break;
   397     default: 
   398       lb=lpx_get_row_lb(lp, i);
   399     }
   400 
   401     switch (b) {
   402     case LPX_FR:
   403     case LPX_LO:
   404       ub = INF;
   405 	break;
   406     default: 
   407       ub=lpx_get_row_ub(lp, i);
   408     }
   409     
   410   }
   411   
   412   void LpGlpk::_setObjCoeff(int i, Value obj_coef)
   413   {
   414     //i=0 means the constant term (shift)
   415     lpx_set_obj_coef(lp, i, obj_coef);
   416   }
   417 
   418   LpGlpk::Value LpGlpk::_getObjCoeff(int i){
   419     //i=0 means the constant term (shift)
   420     return lpx_get_obj_coef(lp, i);
   421   }
   422 
   423   void LpGlpk::_clearObj()
   424   {
   425     for (int i=0;i<=lpx_get_num_cols(lp);++i){
   426       lpx_set_obj_coef(lp, i, 0);
   427     }
   428   }
   429 
   430   LpGlpk::SolveExitStatus LpGlpk::_solve()
   431   {
   432     // A way to check the problem to be solved
   433     //lpx_write_cpxlp(lp,"naittvan.cpx");    
   434 
   435     lpx_std_basis(lp);
   436     int i =  lpx_simplex(lp);
   437     
   438     switch (i) {
   439     case LPX_E_OK: 
   440       return SOLVED;
   441     default:
   442       return UNSOLVED;
   443     }
   444   }
   445 
   446   LpGlpk::Value LpGlpk::_getPrimal(int i)
   447   {
   448     return lpx_get_col_prim(lp,i);
   449   }
   450 
   451   LpGlpk::Value LpGlpk::_getDual(int i)
   452   {
   453     return lpx_get_row_dual(lp,i);
   454   }
   455   
   456   LpGlpk::Value LpGlpk::_getPrimalValue()
   457   {
   458     return lpx_get_obj_val(lp);
   459   }
   460   bool LpGlpk::_isBasicCol(int i) {
   461     return (lpx_get_col_stat(lp, i)==LPX_BS);
   462   }
   463   
   464  
   465   LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
   466   {
   467     int stat=  lpx_get_status(lp);
   468     switch (stat) {
   469     case LPX_UNDEF://Undefined (no solve has been run yet)
   470       return UNDEFINED;
   471     case LPX_NOFEAS://There is no feasible solution (primal, I guess)
   472     case LPX_INFEAS://Infeasible 
   473       return INFEASIBLE;
   474     case LPX_UNBND://Unbounded
   475       return INFINITE;
   476     case LPX_FEAS://Feasible
   477       return FEASIBLE;
   478     case LPX_OPT://Feasible
   479       return OPTIMAL;
   480     default:
   481       return UNDEFINED; //to avoid gcc warning
   482       //FIXME error
   483     }
   484   }
   485 
   486   LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
   487   {
   488 //     std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
   489 //     std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
   490 
   491     switch (lpx_get_dual_stat(lp)) {
   492     case LPX_D_UNDEF://Undefined (no solve has been run yet)
   493       return UNDEFINED;
   494     case LPX_D_NOFEAS://There is no dual feasible solution 
   495 //    case LPX_D_INFEAS://Infeasible 
   496       return INFEASIBLE;
   497     case LPX_D_FEAS://Feasible    
   498       switch (lpx_get_status(lp)) {
   499       case LPX_NOFEAS:
   500 	return INFINITE;
   501       case LPX_OPT:
   502 	return OPTIMAL;
   503       default:
   504 	return FEASIBLE;
   505       }
   506     default:
   507       return UNDEFINED; //to avoid gcc warning
   508       //FIXME error
   509     }
   510   }
   511 
   512   LpGlpk::ProblemTypes LpGlpk::_getProblemType()
   513   {
   514       //int stat=  lpx_get_status(lp);
   515     int statp=  lpx_get_prim_stat(lp);
   516     int statd=  lpx_get_dual_stat(lp);
   517     if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
   518 	return PRIMAL_DUAL_FEASIBLE;
   519     if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
   520 	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   521     if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
   522 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
   523     if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
   524 	return PRIMAL_DUAL_INFEASIBLE;
   525     //In all other cases
   526     return UNKNOWN;
   527   }
   528 
   529   void LpGlpk::_setMax()
   530   {
   531     lpx_set_obj_dir(lp, LPX_MAX);
   532   }
   533 
   534   void LpGlpk::_setMin()
   535   {
   536     lpx_set_obj_dir(lp, LPX_MIN);
   537   }
   538 
   539   bool LpGlpk::_isMax()
   540   {
   541     return (lpx_get_obj_dir(lp)==LPX_MAX);
   542   }
   543 
   544  
   545 
   546   void LpGlpk::messageLevel(int m)
   547   {
   548     lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
   549   }
   550 
   551   void LpGlpk::presolver(bool b)
   552   {
   553     lpx_set_int_parm(lp, LPX_K_PRESOL, b);
   554   }
   555 
   556  
   557 } //END OF NAMESPACE LEMON