lemon/lp_glpk.cc
author deba
Thu, 15 Feb 2007 19:15:14 +0000
changeset 2364 3a5e67bd42d2
parent 2363 2aabce558574
child 2366 bfbdded3763a
permissions -rw-r--r--
Lp row and col getter function
lp section reader and writer for lemon IO
     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, ConstRowIterator b, ConstRowIterator 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(ConstRowIterator 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::_getRowCoeffs(int i, RowIterator b) 
   146   {
   147     int length = lpx_get_mat_row(lp, i, 0, 0);
   148     
   149     std::vector<int> indices(length + 1);
   150     std::vector<Value> values(length + 1);
   151     
   152     lpx_get_mat_row(lp, i, &indices[0], &values[0]);
   153     
   154     for (int i = 1; i <= length; ++i) {
   155       *b = std::make_pair(indices[i], values[i]);
   156       ++b;
   157     }
   158   }
   159   
   160   void LpGlpk::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) {
   161 
   162     std::vector<int> indices;
   163     std::vector<Value> values;
   164 
   165     indices.push_back(0);
   166     values.push_back(0);
   167 
   168     for(ConstColIterator it=b; it!=e; ++it) {
   169       indices.push_back(it->first);
   170       values.push_back(it->second);
   171     }
   172     
   173     lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]);
   174   }
   175 
   176   void LpGlpk::_getColCoeffs(int i, ColIterator b) 
   177   {
   178     int length = lpx_get_mat_col(lp, i, 0, 0);
   179     
   180     std::vector<int> indices(length + 1);
   181     std::vector<Value> values(length + 1);
   182     
   183     lpx_get_mat_col(lp, i, &indices[0], &values[0]);
   184     
   185     for (int i = 1; i <= length; ++i) {
   186       *b = std::make_pair(indices[i], values[i]);
   187       ++b;
   188     }
   189   }
   190 
   191   void LpGlpk::_setCoeff(int row, int col, Value value) 
   192   {
   193 
   194     if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
   195 
   196       int length=lpx_get_mat_row(lp, row, 0, 0);
   197       
   198       std::vector<int> indices(length + 2);
   199       std::vector<Value> values(length + 2);
   200       
   201       lpx_get_mat_row(lp, row, &indices[0], &values[0]);
   202       
   203       //The following code does not suppose that the elements of the
   204       //array indices are sorted
   205       bool found=false;
   206       for (int i = 1; i <= length; ++i) {
   207         if (indices[i]==col){
   208           found=true;
   209           values[i]=value;
   210           break;
   211         }
   212       }
   213       if (!found){
   214         ++length;
   215         indices[length]=col;
   216         values[length]=value;
   217       }
   218     
   219       lpx_set_mat_row(lp, row, length, &indices[0], &values[0]);
   220 
   221     } else {
   222 
   223       int length=lpx_get_mat_col(lp, col, 0, 0);
   224       
   225       std::vector<int> indices(length + 2);
   226       std::vector<Value> values(length + 2);
   227       
   228       lpx_get_mat_col(lp, col, &indices[0], &values[0]);
   229       
   230       //The following code does not suppose that the elements of the
   231       //array indices are sorted
   232       bool found=false;
   233       for (int i = 1; i <= length; ++i) {
   234         if (indices[i]==col){
   235           found=true;
   236           values[i]=value;
   237           break;
   238         }
   239       }
   240       if (!found){
   241         ++length;
   242         indices[length]=row;
   243         values[length]=value;
   244       }
   245     
   246       lpx_set_mat_col(lp, col, length, &indices[0], &values[0]);
   247     }
   248   }
   249 
   250   LpGlpk::Value LpGlpk::_getCoeff(int row, int col)
   251   {
   252 
   253     int length=lpx_get_mat_row(lp, row, 0, 0);
   254     
   255     std::vector<int> indices(length + 1);
   256     std::vector<Value> values(length + 1);
   257     
   258     lpx_get_mat_row(lp, row, &indices[0], &values[0]);
   259     
   260     //The following code does not suppose that the elements of the
   261     //array indices are sorted
   262     for (int i = 1; i <= length; ++i) {
   263       if (indices[i]==col){
   264 	return values[i];
   265       }
   266     }
   267     return 0;
   268 
   269   }
   270 
   271 
   272   void LpGlpk::_setColLowerBound(int i, Value lo)
   273   {
   274     if (lo==INF) {
   275       //FIXME error
   276     }
   277     int b=lpx_get_col_type(lp, i);
   278     double up=lpx_get_col_ub(lp, i);	
   279     if (lo==-INF) {
   280       switch (b) {
   281       case LPX_FR:
   282       case LPX_LO:
   283 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   284 	break;
   285       case LPX_UP:
   286 	break;
   287       case LPX_DB:
   288       case LPX_FX:
   289 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   290 	break;
   291       default: ;
   292 	//FIXME error
   293       }
   294     } else {
   295       switch (b) {
   296       case LPX_FR:
   297       case LPX_LO:
   298 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   299 	break;
   300       case LPX_UP:	  
   301       case LPX_DB:
   302       case LPX_FX:
   303 	if (lo==up) 
   304 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   305 	else 
   306 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   307 	break;
   308       default: ;
   309 	//FIXME error
   310       }
   311     }
   312 
   313   }
   314 
   315   LpGlpk::Value LpGlpk::_getColLowerBound(int i)
   316   {
   317     int b=lpx_get_col_type(lp, i);
   318       switch (b) {
   319       case LPX_LO:
   320       case LPX_DB:
   321       case LPX_FX:
   322 	return lpx_get_col_lb(lp, i);	
   323       default: ;
   324 	return -INF;
   325       }
   326   }
   327   
   328   void LpGlpk::_setColUpperBound(int i, Value up)
   329   {
   330     if (up==-INF) {
   331       //FIXME error
   332     }
   333     int b=lpx_get_col_type(lp, i);
   334     double lo=lpx_get_col_lb(lp, i);
   335     if (up==INF) {
   336       switch (b) {
   337       case LPX_FR:
   338       case LPX_LO:
   339 	break;
   340       case LPX_UP:
   341 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   342 	break;
   343       case LPX_DB:
   344       case LPX_FX:
   345 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   346 	break;
   347       default: ;
   348 	//FIXME error
   349       }
   350     } else {
   351       switch (b) {
   352       case LPX_FR:
   353 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   354 	break;
   355       case LPX_UP:
   356 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   357 	break;
   358       case LPX_LO:
   359       case LPX_DB:
   360       case LPX_FX:
   361 	if (lo==up) 
   362 	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   363 	else 
   364 	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   365 	break;
   366       default: ;
   367 	//FIXME error
   368       }
   369     }
   370   }
   371 
   372   LpGlpk::Value LpGlpk::_getColUpperBound(int i)
   373   {
   374     int b=lpx_get_col_type(lp, i);
   375       switch (b) {
   376       case LPX_UP:
   377       case LPX_DB:
   378       case LPX_FX:
   379 	return lpx_get_col_ub(lp, i);	
   380       default: ;
   381 	return INF;
   382       }
   383   }
   384   
   385   void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
   386   {
   387     //Bad parameter
   388     if (lb==INF || ub==-INF) {
   389       //FIXME error
   390     }
   391 
   392     if (lb == -INF){
   393       if (ub == INF){
   394 	lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
   395       }
   396       else{
   397 	lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
   398       }
   399     }
   400     else{
   401       if (ub==INF){
   402 	lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
   403 
   404       }
   405       else{
   406 	if (lb == ub){
   407 	  lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
   408 	}
   409 	else{
   410 	  lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
   411 	}
   412       }
   413     }
   414 
   415   }
   416 
   417   void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub)
   418   {
   419 
   420     int b=lpx_get_row_type(lp, i);
   421     switch (b) {
   422     case LPX_FR:
   423     case LPX_UP:
   424       lb = -INF;
   425 	break;
   426     default: 
   427       lb=lpx_get_row_lb(lp, i);
   428     }
   429 
   430     switch (b) {
   431     case LPX_FR:
   432     case LPX_LO:
   433       ub = INF;
   434 	break;
   435     default: 
   436       ub=lpx_get_row_ub(lp, i);
   437     }
   438     
   439   }
   440   
   441   void LpGlpk::_setObjCoeff(int i, Value obj_coef)
   442   {
   443     //i=0 means the constant term (shift)
   444     lpx_set_obj_coef(lp, i, obj_coef);
   445   }
   446 
   447   LpGlpk::Value LpGlpk::_getObjCoeff(int i){
   448     //i=0 means the constant term (shift)
   449     return lpx_get_obj_coef(lp, i);
   450   }
   451 
   452   void LpGlpk::_clearObj()
   453   {
   454     for (int i=0;i<=lpx_get_num_cols(lp);++i){
   455       lpx_set_obj_coef(lp, i, 0);
   456     }
   457   }
   458 
   459   LpGlpk::SolveExitStatus LpGlpk::_solve()
   460   {
   461     // A way to check the problem to be solved
   462     //lpx_write_cpxlp(lp,"naittvan.cpx");    
   463 
   464     lpx_std_basis(lp);
   465     int i =  lpx_simplex(lp);
   466     
   467     switch (i) {
   468     case LPX_E_OK: 
   469       return SOLVED;
   470     default:
   471       return UNSOLVED;
   472     }
   473   }
   474 
   475   LpGlpk::Value LpGlpk::_getPrimal(int i)
   476   {
   477     return lpx_get_col_prim(lp,i);
   478   }
   479 
   480   LpGlpk::Value LpGlpk::_getDual(int i)
   481   {
   482     return lpx_get_row_dual(lp,i);
   483   }
   484   
   485   LpGlpk::Value LpGlpk::_getPrimalValue()
   486   {
   487     return lpx_get_obj_val(lp);
   488   }
   489   bool LpGlpk::_isBasicCol(int i) {
   490     return (lpx_get_col_stat(lp, i)==LPX_BS);
   491   }
   492   
   493  
   494   LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
   495   {
   496     int stat=  lpx_get_status(lp);
   497     switch (stat) {
   498     case LPX_UNDEF://Undefined (no solve has been run yet)
   499       return UNDEFINED;
   500     case LPX_NOFEAS://There is no feasible solution (primal, I guess)
   501     case LPX_INFEAS://Infeasible 
   502       return INFEASIBLE;
   503     case LPX_UNBND://Unbounded
   504       return INFINITE;
   505     case LPX_FEAS://Feasible
   506       return FEASIBLE;
   507     case LPX_OPT://Feasible
   508       return OPTIMAL;
   509     default:
   510       return UNDEFINED; //to avoid gcc warning
   511       //FIXME error
   512     }
   513   }
   514 
   515   LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
   516   {
   517 //     std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
   518 //     std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
   519 
   520     switch (lpx_get_dual_stat(lp)) {
   521     case LPX_D_UNDEF://Undefined (no solve has been run yet)
   522       return UNDEFINED;
   523     case LPX_D_NOFEAS://There is no dual feasible solution 
   524 //    case LPX_D_INFEAS://Infeasible 
   525       return INFEASIBLE;
   526     case LPX_D_FEAS://Feasible    
   527       switch (lpx_get_status(lp)) {
   528       case LPX_NOFEAS:
   529 	return INFINITE;
   530       case LPX_OPT:
   531 	return OPTIMAL;
   532       default:
   533 	return FEASIBLE;
   534       }
   535     default:
   536       return UNDEFINED; //to avoid gcc warning
   537       //FIXME error
   538     }
   539   }
   540 
   541   LpGlpk::ProblemTypes LpGlpk::_getProblemType()
   542   {
   543       //int stat=  lpx_get_status(lp);
   544     int statp=  lpx_get_prim_stat(lp);
   545     int statd=  lpx_get_dual_stat(lp);
   546     if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
   547 	return PRIMAL_DUAL_FEASIBLE;
   548     if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
   549 	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   550     if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
   551 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
   552     if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
   553 	return PRIMAL_DUAL_INFEASIBLE;
   554     //In all other cases
   555     return UNKNOWN;
   556   }
   557 
   558   void LpGlpk::_setMax()
   559   {
   560     lpx_set_obj_dir(lp, LPX_MAX);
   561   }
   562 
   563   void LpGlpk::_setMin()
   564   {
   565     lpx_set_obj_dir(lp, LPX_MIN);
   566   }
   567 
   568   bool LpGlpk::_isMax()
   569   {
   570     return (lpx_get_obj_dir(lp)==LPX_MAX);
   571   }
   572 
   573  
   574 
   575   void LpGlpk::messageLevel(int m)
   576   {
   577     lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
   578   }
   579 
   580   void LpGlpk::presolver(bool b)
   581   {
   582     lpx_set_int_parm(lp, LPX_K_PRESOL, b);
   583   }
   584 
   585  
   586 } //END OF NAMESPACE LEMON