src/work/marci/lp/lp_solver_wrapper_3.h
author jacint
Thu, 27 Jan 2005 16:11:54 +0000
changeset 1098 e3b3667c6857
parent 1081 c0ad2673b11f
child 1099 91a8ee9d088d
permissions -rw-r--r--
(none)
     1 // -*- c++ -*-
     2 #ifndef LEMON_LP_SOLVER_WRAPPER_H
     3 #define LEMON_LP_SOLVER_WRAPPER_H
     4 
     5 ///\ingroup misc
     6 ///\file
     7 ///\brief Dijkstra algorithm.
     8 
     9 // #include <stdio.h>
    10 #include <stdlib.h>
    11 #include <iostream>
    12 #include <map>
    13 // #include <stdio>
    14 //#include <stdlib>
    15 extern "C" {
    16 #include "glpk.h"
    17 }
    18 
    19 #include <iostream>
    20 #include <vector>
    21 #include <string>
    22 #include <list>
    23 #include <memory>
    24 #include <utility>
    25 
    26 //#include <sage_graph.h>
    27 //#include <lemon/list_graph.h>
    28 //#include <lemon/graph_wrapper.h>
    29 #include <lemon/invalid.h>
    30 //#include <bfs_dfs.h>
    31 //#include <stp.h>
    32 //#include <lemon/max_flow.h>
    33 //#include <augmenting_flow.h>
    34 //#include <iter_map.h>
    35 
    36 using std::cout;
    37 using std::cin;
    38 using std::endl;
    39 
    40 namespace lemon {
    41   
    42   /// \addtogroup misc
    43   /// @{
    44 
    45   /// \brief A partitioned vector with iterable classes.
    46   ///
    47   /// This class implements a container in which the data is stored in an 
    48   /// stl vector, the range is partitioned into sets and each set is 
    49   /// doubly linked in a list. 
    50   /// That is, each class is iterable by lemon iterators, and any member of 
    51   /// the vector can bo moved to an other class.
    52   template <typename T>
    53   class IterablePartition {
    54   protected:
    55     struct Node {
    56       T data;
    57       int prev; //invalid az -1
    58       int next; 
    59     };
    60     std::vector<Node> nodes;
    61     struct Tip {
    62       int first;
    63       int last;
    64     };
    65     std::vector<Tip> tips;
    66   public:
    67     /// The classes are indexed by integers from \c 0 to \c classNum()-1.
    68     int classNum() const { return tips.size(); }
    69     /// This lemon style iterator iterates through a class. 
    70     class ClassIt;
    71     /// Constructor. The number of classes is to be given which is fixed 
    72     /// over the life of the container. 
    73     /// The partition classes are indexed from 0 to class_num-1. 
    74     IterablePartition(int class_num) { 
    75       for (int i=0; i<class_num; ++i) {
    76 	Tip t;
    77 	t.first=t.last=-1;
    78 	tips.push_back(t);
    79       }
    80     }
    81   protected:
    82     void befuz(ClassIt it, int class_id) {
    83       if (tips[class_id].first==-1) {
    84 	if (tips[class_id].last==-1) {
    85 	  nodes[it.i].prev=nodes[it.i].next=-1;
    86 	  tips[class_id].first=tips[class_id].last=it.i;
    87 	}
    88       } else {
    89 	nodes[it.i].prev=tips[class_id].last;
    90 	nodes[it.i].next=-1;
    91 	nodes[tips[class_id].last].next=it.i;
    92 	tips[class_id].last=it.i;
    93       }
    94     }
    95     void kifuz(ClassIt it, int class_id) {
    96       if (tips[class_id].first==it.i) {
    97 	if (tips[class_id].last==it.i) {
    98 	  tips[class_id].first=tips[class_id].last=-1;
    99 	} else {
   100 	  tips[class_id].first=nodes[it.i].next;
   101 	  nodes[nodes[it.i].next].prev=-1;
   102 	}
   103       } else {
   104 	if (tips[class_id].last==it.i) {
   105 	  tips[class_id].last=nodes[it.i].prev;
   106 	  nodes[nodes[it.i].prev].next=-1;
   107 	} else {
   108 	  nodes[nodes[it.i].next].prev=nodes[it.i].prev;
   109 	  nodes[nodes[it.i].prev].next=nodes[it.i].next;
   110 	}
   111       }
   112     }
   113   public:
   114     /// A new element with data \c t is pushed into the vector and into class 
   115     /// \c class_id.
   116     ClassIt push_back(const T& t, int class_id) { 
   117       Node n;
   118       n.data=t;
   119       nodes.push_back(n);
   120       int i=nodes.size()-1;
   121       befuz(i, class_id);
   122       return i;
   123     }
   124     /// A member is moved to an other class.
   125     void set(ClassIt it, int old_class_id, int new_class_id) {
   126       kifuz(it.i, old_class_id);
   127       befuz(it.i, new_class_id);
   128     }
   129     /// Returns the data pointed by \c it.
   130     T& operator[](ClassIt it) { return nodes[it.i].data; }
   131     /// Returns the data pointed by \c it.
   132     const T& operator[](ClassIt it) const { return nodes[it.i].data; }
   133     ///.
   134     class ClassIt {
   135       friend class IterablePartition;
   136     protected:
   137       int i;
   138     public:
   139       /// Default constructor.
   140       ClassIt() { }
   141       /// This constructor constructs an iterator which points
   142       /// to the member of th container indexed by the integer _i.
   143       ClassIt(const int& _i) : i(_i) { }
   144       /// Invalid constructor.
   145       ClassIt(const Invalid&) : i(-1) { }
   146     };
   147     /// First member of class \c class_id.
   148     ClassIt& first(ClassIt& it, int class_id) const {
   149       it.i=tips[class_id].first;
   150       return it;
   151     }
   152     /// Next member.
   153     ClassIt& next(ClassIt& it) const {
   154       it.i=nodes[it.i].next;
   155       return it;
   156     }
   157     /// True iff the iterator is valid.
   158     bool valid(const ClassIt& it) const { return it.i!=-1; }
   159   };
   160 
   161   template <typename _Col, typename _Value>
   162   class Expr;
   163 
   164   template <typename _Col, typename _Value>
   165   class SmallExpr {
   166     template <typename _C, typename _V> 
   167     friend class Expr;
   168   protected:
   169     _Col col;
   170     _Value value;
   171   public:
   172     SmallExpr(_Col _col) : col(_col), value(1) { 
   173     }
   174     SmallExpr& operator *= (_Value _value) {
   175       value*=_value;
   176       return *this;
   177     }
   178     //    template <typename _C, typename _V>
   179     //    friend SmallExpr<_C, _V> operator* (_V _value, 
   180     //					const SmallExpr<_C, _V>& expr);
   181     template <typename _C, typename _V>
   182     friend std::ostream& operator<<(std::ostream& os, 
   183 				    const SmallExpr<_C, _V>& expr);
   184   };
   185 
   186   template <typename _Col, typename _Value>
   187   SmallExpr<_Col, _Value> 
   188   operator* (_Value value, 
   189 	     const SmallExpr<_Col, _Value>& expr) {
   190     SmallExpr<_Col, _Value> tmp;
   191     tmp=expr;
   192     tmp*=value;
   193     return tmp;
   194   }
   195 
   196   template <typename _Col, typename _Value>
   197   std::ostream& operator<<(std::ostream& os, 
   198 			   const SmallExpr<_Col, _Value>& expr) {
   199     os << expr.value << "*" << expr.col;
   200     return os;
   201   }
   202 
   203   template <typename _Col, typename _Value>
   204   class Expr {
   205   protected:
   206     typedef 
   207     typename std::map<_Col, _Value> Data; 
   208     Data data;
   209   public:
   210     Expr() { }
   211     Expr(SmallExpr<_Col, _Value> expr) { 
   212       data.insert(std::make_pair(expr.col, expr.value));
   213     }
   214 //     Expr(_Col col) { 
   215 //       data.insert(std::make_pair(col, 1));
   216 //     }
   217     Expr& operator*=(_Value _value) {
   218       for (typename Data::iterator i=data.begin(); 
   219 	   i!=data.end(); ++i) {
   220 	(*i).second *= _value;
   221       }
   222       return *this;
   223     }
   224     Expr& operator+=(SmallExpr<_Col, _Value> expr) {
   225       typename Data::iterator i=data.find(expr.col);
   226       if (i==data.end()) {
   227 	data.insert(std::make_pair(expr.col, expr.value));
   228       } else {
   229 	(*i).second+=expr.value;
   230       }
   231       return *this;
   232     }
   233     //    template <typename _C, typename _V> 
   234     //    friend Expr<_C, _V> operator*(_V _value, const Expr<_C, _V>& expr);
   235     template <typename _C, typename _V> 
   236     friend std::ostream& operator<<(std::ostream& os, 
   237 				    const Expr<_C, _V>& expr);
   238   };
   239 
   240   template <typename _Col, typename _Value>
   241   Expr<_Col, _Value> operator*(_Value _value, 
   242 			       const Expr<_Col, _Value>& expr) {
   243     Expr<_Col, _Value> tmp;
   244     tmp=expr;
   245     tmp*=_value;
   246     return tmp;
   247   }
   248 
   249   template <typename _Col, typename _Value>
   250   std::ostream& operator<<(std::ostream& os, 
   251 			   const Expr<_Col, _Value>& expr) {
   252     for (typename Expr<_Col, _Value>::Data::const_iterator i=
   253 	   expr.data.begin(); 
   254 	 i!=expr.data.end(); ++i) {
   255       os << (*i).second << "*" << (*i).first << " ";
   256     }
   257     return os;
   258   }
   259 
   260   /*! \e
   261    */
   262   template <typename _Value>
   263   class LPSolverBase {
   264   public:
   265     /// \e
   266     typedef _Value Value;
   267     /// \e
   268     typedef IterablePartition<int>::ClassIt RowIt;
   269     /// \e
   270     typedef IterablePartition<int>::ClassIt ColIt;
   271   public:
   272     /// \e
   273     IterablePartition<int> row_iter_map;
   274     /// \e
   275     IterablePartition<int> col_iter_map;
   276     /// \e
   277     const int VALID_CLASS;
   278     /// \e
   279     const int INVALID_CLASS;
   280   public:
   281     /// \e
   282     LPSolverBase() : row_iter_map(2), 
   283 		     col_iter_map(2), 
   284 		     VALID_CLASS(0), INVALID_CLASS(1) { }
   285     /// \e
   286     virtual ~LPSolverBase() { }
   287 
   288     //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
   289 
   290   public:
   291     /// \e
   292     virtual void setMinimize() = 0;
   293     /// \e
   294     virtual void setMaximize() = 0;
   295 
   296     //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
   297 
   298   protected:
   299     /// \e
   300     virtual int _addRow() = 0;
   301     /// \e
   302     virtual int _addCol() = 0;
   303     /// \e
   304     virtual void _setRowCoeffs(int i, 
   305 			       std::vector<std::pair<int, double> > coeffs) = 0;
   306     /// \e
   307     virtual void _setColCoeffs(int i, 
   308 			       std::vector<std::pair<int, double> > coeffs) = 0;
   309     /// \e
   310     virtual void _eraseCol(int i) = 0;
   311     /// \e
   312     virtual void _eraseRow(int i) = 0;
   313   public:
   314     /// \e
   315     enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
   316   protected:
   317     /// \e
   318     virtual void _setColBounds(int i, Bound bound, 
   319 			       _Value lo, _Value up) = 0; 
   320     /// \e
   321     virtual void _setRowBounds(int i, Bound bound, 
   322 			       _Value lo, _Value up) = 0; 
   323     /// \e
   324     virtual void _setObjCoef(int i, _Value obj_coef) = 0;
   325     /// \e
   326     virtual _Value _getObjCoef(int i) = 0;
   327 
   328     //LOW LEVEL, SOLUTION RETRIEVING FUNCTIONS
   329 
   330   protected:
   331     virtual _Value _getPrimal(int i) = 0;
   332 
   333     //HIGH LEVEL INTERFACE, MATRIX MANIPULATING FUNTIONS
   334 
   335   public:
   336     /// \e
   337     RowIt addRow() {
   338       int i=_addRow(); 
   339       RowIt row_it;
   340       row_iter_map.first(row_it, INVALID_CLASS);
   341       if (row_iter_map.valid(row_it)) { //van hasznalhato hely
   342 	row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
   343 	row_iter_map[row_it]=i;
   344       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   345 	row_it=row_iter_map.push_back(i, VALID_CLASS);
   346       }
   347       return row_it;
   348     }
   349     /// \e
   350     ColIt addCol() {
   351       int i=_addCol();  
   352       ColIt col_it;
   353       col_iter_map.first(col_it, INVALID_CLASS);
   354       if (col_iter_map.valid(col_it)) { //van hasznalhato hely
   355 	col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
   356 	col_iter_map[col_it]=i;
   357       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   358 	col_it=col_iter_map.push_back(i, VALID_CLASS);
   359       }
   360       return col_it;
   361     }
   362     /// \e
   363     template <typename Begin, typename End>
   364     void setRowCoeffs(RowIt row_it, Begin begin, End end) {
   365       std::vector<std::pair<int, double> > coeffs;
   366       for ( ; begin!=end; ++begin) {
   367 	coeffs.push_back(std::
   368 			 make_pair(col_iter_map[begin->first], begin->second));
   369       }
   370       _setRowCoeffs(row_iter_map[row_it], coeffs);
   371     }
   372     /// \e
   373     template <typename Begin, typename End>
   374     void setColCoeffs(ColIt col_it, Begin begin, End end) {
   375       std::vector<std::pair<int, double> > coeffs;
   376       for ( ; begin!=end; ++begin) {
   377 	coeffs.push_back(std::
   378 			 make_pair(row_iter_map[begin->first], begin->second));
   379       }
   380       _setColCoeffs(col_iter_map[col_it], coeffs);
   381     }
   382     /// \e
   383     void eraseCol(const ColIt& col_it) {
   384       col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
   385       int cols[2];
   386       cols[1]=col_iter_map[col_it];
   387       _eraseCol(cols[1]);
   388       col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
   389       ColIt it;
   390       for (col_iter_map.first(it, VALID_CLASS); 
   391 	   col_iter_map.valid(it); col_iter_map.next(it)) {
   392 	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
   393       }
   394     }
   395     /// \e
   396     void eraseRow(const RowIt& row_it) {
   397       row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
   398       int rows[2];
   399       rows[1]=row_iter_map[row_it];
   400       _eraseRow(rows[1]);
   401       row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
   402       RowIt it;
   403       for (row_iter_map.first(it, VALID_CLASS); 
   404 	   row_iter_map.valid(it); row_iter_map.next(it)) {
   405 	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
   406       }
   407     }
   408     /// \e
   409     void setColBounds(const ColIt& col_it, Bound bound, 
   410 		      _Value lo, _Value up) {
   411       _setColBounds(col_iter_map[col_it], bound, lo, up);
   412     }
   413     /// \e
   414     void setRowBounds(const RowIt& row_it, Bound bound, 
   415 		      _Value lo, _Value up) {
   416       _setRowBounds(row_iter_map[row_it], bound, lo, up);
   417     }
   418     /// \e
   419     void setObjCoef(const ColIt& col_it, _Value obj_coef) {
   420       _setObjCoef(col_iter_map[col_it], obj_coef);
   421     }
   422     /// \e
   423     _Value getObjCoef(const ColIt& col_it) {
   424       return _getObjCoef(col_iter_map[col_it]);
   425     }
   426 
   427     //SOLVER FUNCTIONS
   428 
   429     /// \e
   430     virtual void solveSimplex() = 0;
   431     /// \e
   432     virtual void solvePrimalSimplex() = 0;
   433     /// \e
   434     virtual void solveDualSimplex() = 0;
   435     /// \e
   436 
   437     //HIGH LEVEL, SOLUTION RETRIEVING FUNCTIONS
   438 
   439   public:
   440     _Value getPrimal(const ColIt& col_it) {
   441       return _getPrimal(col_iter_map[col_it]);
   442     }
   443     /// \e
   444     virtual _Value getObjVal() = 0;
   445 
   446     //OTHER FUNCTIONS
   447 
   448     /// \e
   449     virtual int rowNum() const = 0;
   450     /// \e
   451     virtual int colNum() const = 0;
   452     /// \e
   453     virtual int warmUp() = 0;
   454     /// \e
   455     virtual void printWarmUpStatus(int i) = 0;
   456     /// \e
   457     virtual int getPrimalStatus() = 0;
   458     /// \e
   459     virtual void printPrimalStatus(int i) = 0;
   460     /// \e
   461     virtual int getDualStatus() = 0;
   462     /// \e
   463     virtual void printDualStatus(int i) = 0;
   464     /// Returns the status of the slack variable assigned to row \c row_it.
   465     virtual int getRowStat(const RowIt& row_it) = 0;
   466     /// \e
   467     virtual void printRowStatus(int i) = 0;
   468     /// Returns the status of the variable assigned to column \c col_it.
   469     virtual int getColStat(const ColIt& col_it) = 0;
   470     /// \e
   471     virtual void printColStatus(int i) = 0;
   472   };
   473   
   474 
   475   /// \brief Wrappers for LP solvers
   476   /// 
   477   /// This class implements a lemon wrapper for glpk.
   478   /// Later other LP-solvers will be wrapped into lemon.
   479   /// The aim of this class is to give a general surface to different 
   480   /// solvers, i.e. it makes possible to write algorithms using LP's, 
   481   /// in which the solver can be changed to an other one easily.
   482   class LPGLPK : public LPSolverBase<double> {
   483   public:
   484     typedef LPSolverBase<double> Parent;
   485 
   486   public:
   487     /// \e
   488     LPX* lp;
   489 
   490   public:
   491     /// \e
   492     LPGLPK() : Parent(), 
   493 			lp(lpx_create_prob()) {
   494       lpx_set_int_parm(lp, LPX_K_DUAL, 1);
   495     }
   496     /// \e
   497     ~LPGLPK() {
   498       lpx_delete_prob(lp);
   499     }
   500 
   501     //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
   502 
   503     /// \e
   504     void setMinimize() { 
   505       lpx_set_obj_dir(lp, LPX_MIN);
   506     }
   507     /// \e
   508     void setMaximize() { 
   509       lpx_set_obj_dir(lp, LPX_MAX);
   510     }
   511 
   512     //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
   513 
   514   protected:
   515     /// \e
   516     int _addCol() { 
   517       return lpx_add_cols(lp, 1);
   518     }
   519     /// \e
   520     int _addRow() { 
   521       return lpx_add_rows(lp, 1);
   522     }
   523     /// \e
   524     virtual void _setRowCoeffs(int i, 
   525 			       std::vector<std::pair<int, double> > coeffs) {
   526       int mem_length=1+colNum();
   527       int* indices = new int[mem_length];
   528       double* doubles = new double[mem_length];
   529       int length=0;
   530       for (std::vector<std::pair<int, double> >::
   531 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   532 	++length;
   533 	indices[length]=it->first;
   534 	doubles[length]=it->second;
   535 // 	std::cout << "  " << indices[length] << " " 
   536 // 		  << doubles[length] << std::endl;
   537       }
   538 //      std::cout << i << " " << length << std::endl;
   539       lpx_set_mat_row(lp, i, length, indices, doubles);
   540       delete [] indices;
   541       delete [] doubles;
   542     }
   543     /// \e
   544     virtual void _setColCoeffs(int i, 
   545 			       std::vector<std::pair<int, double> > coeffs) {
   546       int mem_length=1+rowNum();
   547       int* indices = new int[mem_length];
   548       double* doubles = new double[mem_length];
   549       int length=0;
   550       for (std::vector<std::pair<int, double> >::
   551 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   552 	++length;
   553 	indices[length]=it->first;
   554 	doubles[length]=it->second;
   555       }
   556       lpx_set_mat_col(lp, i, length, indices, doubles);
   557       delete [] indices;
   558       delete [] doubles;
   559     }
   560     /// \e
   561     virtual void _eraseCol(int i) {
   562       int cols[2];
   563       cols[1]=i;
   564       lpx_del_cols(lp, 1, cols);
   565     }
   566     virtual void _eraseRow(int i) {
   567       int rows[2];
   568       rows[1]=i;
   569       lpx_del_rows(lp, 1, rows);
   570     }
   571     virtual void _setColBounds(int i, Bound bound, 
   572 			       double lo, double up) {
   573       switch (bound) {
   574       case FREE:
   575 	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   576 	break;
   577       case LOWER:
   578 	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   579 	break;
   580       case UPPER:
   581 	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   582 	break;
   583       case DOUBLE:
   584 	lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   585 	break;
   586       case FIXED:
   587 	lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   588 	break;
   589       }
   590     } 
   591     virtual void _setRowBounds(int i, Bound bound, 
   592 			       double lo, double up) {
   593       switch (bound) {
   594       case FREE:
   595 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
   596 	break;
   597       case LOWER:
   598 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
   599 	break;
   600       case UPPER:
   601 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   602 	break;
   603       case DOUBLE:
   604 	lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   605 	break;
   606       case FIXED:
   607 	lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   608 	break;
   609       }
   610     } 
   611   protected:
   612     /// \e
   613     virtual double _getObjCoef(int i) { 
   614       return lpx_get_obj_coef(lp, i);
   615     }
   616     /// \e
   617     virtual void _setObjCoef(int i, double obj_coef) { 
   618       lpx_set_obj_coef(lp, i, obj_coef);
   619     }
   620   public:
   621     /// \e
   622     void solveSimplex() { lpx_simplex(lp); }
   623     /// \e
   624     void solvePrimalSimplex() { lpx_simplex(lp); }
   625     /// \e
   626     void solveDualSimplex() { lpx_simplex(lp); }
   627     /// \e
   628   protected:
   629     virtual double _getPrimal(int i) {
   630       return lpx_get_col_prim(lp, i);
   631     }
   632   public:
   633     /// \e
   634     double getObjVal() { return lpx_get_obj_val(lp); }
   635     /// \e
   636     int rowNum() const { return lpx_get_num_rows(lp); }
   637     /// \e
   638     int colNum() const { return lpx_get_num_cols(lp); }
   639     /// \e
   640     int warmUp() { return lpx_warm_up(lp); }
   641     /// \e
   642     void printWarmUpStatus(int i) {
   643       switch (i) {
   644       case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
   645       case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
   646       case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
   647       case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
   648       }
   649     }
   650     /// \e
   651     int getPrimalStatus() { return lpx_get_prim_stat(lp); }
   652     /// \e
   653     void printPrimalStatus(int i) {
   654       switch (i) {
   655       case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
   656       case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
   657       case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
   658       case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
   659       }
   660     }
   661     /// \e
   662     int getDualStatus() { return lpx_get_dual_stat(lp); }
   663     /// \e
   664     void printDualStatus(int i) {
   665       switch (i) {
   666       case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
   667       case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
   668       case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
   669       case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
   670       }
   671     }
   672     /// Returns the status of the slack variable assigned to row \c row_it.
   673     int getRowStat(const RowIt& row_it) { 
   674       return lpx_get_row_stat(lp, row_iter_map[row_it]); 
   675     }
   676     /// \e
   677     void printRowStatus(int i) {
   678       switch (i) {
   679       case LPX_BS: cout << "LPX_BS" << endl; break;
   680       case LPX_NL: cout << "LPX_NL" << endl; break;	
   681       case LPX_NU: cout << "LPX_NU" << endl; break;
   682       case LPX_NF: cout << "LPX_NF" << endl; break;
   683       case LPX_NS: cout << "LPX_NS" << endl; break;
   684       }
   685     }
   686     /// Returns the status of the variable assigned to column \c col_it.
   687     int getColStat(const ColIt& col_it) { 
   688       return lpx_get_col_stat(lp, col_iter_map[col_it]); 
   689     }
   690     /// \e
   691     void printColStatus(int i) {
   692       switch (i) {
   693       case LPX_BS: cout << "LPX_BS" << endl; break;
   694       case LPX_NL: cout << "LPX_NL" << endl; break;	
   695       case LPX_NU: cout << "LPX_NU" << endl; break;
   696       case LPX_NF: cout << "LPX_NF" << endl; break;
   697       case LPX_NS: cout << "LPX_NS" << endl; break;
   698       }
   699     }
   700   };
   701   
   702   /// @}
   703 
   704 } //namespace lemon
   705 
   706 #endif //LEMON_LP_SOLVER_WRAPPER_H