src/work/marci/lp/lp_solver_base.h
author marci
Tue, 01 Feb 2005 15:26:47 +0000
changeset 1112 b258584569f2
parent 1111 88ade201ffc6
child 1113 b5ad821053a1
permissions -rw-r--r--
try of grouping for documentation
     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 <limits>
    14 // #include <stdio>
    15 //#include <stdlib>
    16 extern "C" {
    17 #include "glpk.h"
    18 }
    19 
    20 #include <iostream>
    21 #include <vector>
    22 #include <string>
    23 #include <list>
    24 #include <memory>
    25 #include <utility>
    26 
    27 //#include <lemon/list_graph.h>
    28 #include <lemon/invalid.h>
    29 #include <expression.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       friend bool operator<(const ClassIt& x, const ClassIt& y);
   147       friend std::ostream& operator<<(std::ostream& os, 
   148 				      const ClassIt& it);
   149     };
   150     friend bool operator<(const ClassIt& x, const ClassIt& y) {
   151       return (x.i < y.i);
   152     }
   153     friend std::ostream& operator<<(std::ostream& os, 
   154 				    const ClassIt& it) {
   155       os << it.i;
   156       return os;
   157     }
   158     /// First member of class \c class_id.
   159     ClassIt& first(ClassIt& it, int class_id) const {
   160       it.i=tips[class_id].first;
   161       return it;
   162     }
   163     /// Next member.
   164     ClassIt& next(ClassIt& it) const {
   165       it.i=nodes[it.i].next;
   166       return it;
   167     }
   168     /// True iff the iterator is valid.
   169     bool valid(const ClassIt& it) const { return it.i!=-1; }
   170   };
   171 
   172 
   173   /*! \e
   174     \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
   175     \todo LEKERDEZESEK!!!
   176     \todo DOKSI!!!! Doxygen group!!!
   177     The aim of this class is to give a general surface to different 
   178     solvers, i.e. it makes possible to write algorithms using LP's, 
   179     in which the solver can be changed to an other one easily.
   180     \nosubgrouping
   181   */
   182   template <typename _Value>
   183   class LPSolverBase {
   184     
   185     /*! @name Unchategorized functions and types (public members)
   186     */
   187     //@{
   188   public:
   189 
   190     //UNCATEGORIZED
   191 
   192     /// \e
   193     typedef _Value Value;
   194     /// \e
   195     typedef IterablePartition<int>::ClassIt RowIt;
   196     /// \e
   197     typedef IterablePartition<int>::ClassIt ColIt;
   198   public:
   199     /// \e
   200     IterablePartition<int> row_iter_map;
   201     /// \e
   202     IterablePartition<int> col_iter_map;
   203     /// \e
   204     const int VALID_CLASS;
   205     /// \e
   206     const int INVALID_CLASS;
   207     /// \e 
   208     static const _Value INF;
   209   public:
   210     /// \e
   211     LPSolverBase() : row_iter_map(2), 
   212 		     col_iter_map(2), 
   213 		     VALID_CLASS(0), INVALID_CLASS(1) { }
   214     /// \e
   215     virtual ~LPSolverBase() { }
   216     //@}
   217 
   218     /*! @name Medium level interface (public members)
   219       These functions appear in the low level and also in the high level 
   220       interfaces thus these each of these functions have to be implemented 
   221       only once in the different interfaces.
   222       This means that these functions have to be reimplemented for all of the 
   223       different lp solvers. These are basic functions, and have the same 
   224       parameter lists in the low and high level interfaces. 
   225     */
   226     //@{
   227   public:
   228 
   229     //UNCATEGORIZED FUNCTIONS
   230 
   231     /// \e
   232     virtual void setMinimize() = 0;
   233     /// \e
   234     virtual void setMaximize() = 0;
   235 
   236     //SOLVER FUNCTIONS
   237 
   238     /// \e
   239     virtual void solveSimplex() = 0;
   240     /// \e
   241     virtual void solvePrimalSimplex() = 0;
   242     /// \e
   243     virtual void solveDualSimplex() = 0;
   244     /// \e
   245 
   246     //SOLUTION RETRIEVING
   247 
   248     /// \e
   249     virtual _Value getObjVal() = 0;
   250 
   251     //OTHER FUNCTIONS
   252 
   253     /// \e
   254     virtual int rowNum() const = 0;
   255     /// \e
   256     virtual int colNum() const = 0;
   257     /// \e
   258     virtual int warmUp() = 0;
   259     /// \e
   260     virtual void printWarmUpStatus(int i) = 0;
   261     /// \e
   262     virtual int getPrimalStatus() = 0;
   263     /// \e
   264     virtual void printPrimalStatus(int i) = 0;
   265     /// \e
   266     virtual int getDualStatus() = 0;
   267     /// \e
   268     virtual void printDualStatus(int i) = 0;
   269     /// Returns the status of the slack variable assigned to row \c row_it.
   270     virtual int getRowStat(const RowIt& row_it) = 0;
   271     /// \e
   272     virtual void printRowStatus(int i) = 0;
   273     /// Returns the status of the variable assigned to column \c col_it.
   274     virtual int getColStat(const ColIt& col_it) = 0;
   275     /// \e
   276     virtual void printColStatus(int i) = 0;
   277 
   278     //@}
   279 
   280     /*! @name Low level interface (protected members)
   281       Problem manipulating functions in the low level interface
   282     */
   283     //@{
   284   protected:
   285 
   286     //MATRIX MANIPULATING FUNCTIONS
   287 
   288     /// \e
   289     virtual int _addCol() = 0;
   290     /// \e
   291     virtual int _addRow() = 0;
   292     /// \e
   293     virtual void _eraseCol(int i) = 0;
   294     /// \e
   295     virtual void _eraseRow(int i) = 0;
   296     /// \e
   297     virtual void _setRowCoeffs(int i, 
   298 			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
   299     /// \e
   300     virtual void _setColCoeffs(int i, 
   301 			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
   302   public:
   303     /// \e
   304     enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
   305   protected:
   306     /// \e
   307     /// The lower bound of a variable (column) have to be given by an 
   308     /// extended number of type _Value, i.e. a finite number of type 
   309     /// _Value or -INF.
   310     virtual void _setColLowerBound(int i, _Value value) = 0;
   311     /// \e
   312     /// The lower bound of a variable (column) is an 
   313     /// extended number of type _Value, i.e. a finite number of type 
   314     /// _Value or -INF.
   315     virtual _Value _getColLowerBound(int i) = 0;
   316     /// \e
   317     /// The upper bound of a variable (column) have to be given by an 
   318     /// extended number of type _Value, i.e. a finite number of type 
   319     /// _Value or INF.
   320     virtual void _setColUpperBound(int i, _Value value) = 0;
   321     /// \e
   322     /// The upper bound of a variable (column) is an 
   323     /// extended number of type _Value, i.e. a finite number of type 
   324     /// _Value or INF.
   325     virtual _Value _getColUpperBound(int i) = 0;
   326     /// \e
   327     /// The lower bound of a linear expression (row) have to be given by an 
   328     /// extended number of type _Value, i.e. a finite number of type 
   329     /// _Value or -INF.
   330     virtual void _setRowLowerBound(int i, _Value value) = 0;
   331     /// \e
   332     /// The lower bound of a linear expression (row) is an 
   333     /// extended number of type _Value, i.e. a finite number of type 
   334     /// _Value or -INF.
   335     virtual _Value _getRowLowerBound(int i) = 0;
   336     /// \e
   337     /// The upper bound of a linear expression (row) have to be given by an 
   338     /// extended number of type _Value, i.e. a finite number of type 
   339     /// _Value or INF.
   340     virtual void _setRowUpperBound(int i, _Value value) = 0;
   341     /// \e
   342     /// The upper bound of a linear expression (row) is an 
   343     /// extended number of type _Value, i.e. a finite number of type 
   344     /// _Value or INF.
   345     virtual _Value _getRowUpperBound(int i) = 0;
   346     /// \e
   347     virtual void _setObjCoef(int i, _Value obj_coef) = 0;
   348     /// \e
   349     virtual _Value _getObjCoef(int i) = 0;
   350     
   351     //SOLUTION RETRIEVING
   352 
   353     /// \e
   354     virtual _Value _getPrimal(int i) = 0;
   355     //@}
   356     
   357     /*! @name High level interface (public members)
   358       Problem manipulating functions in the high level interface
   359     */
   360     //@{
   361   public:
   362 
   363     //MATRIX MANIPULATING FUNCTIONS
   364 
   365     /// \e
   366     ColIt addCol() {
   367       int i=_addCol();  
   368       ColIt col_it;
   369       col_iter_map.first(col_it, INVALID_CLASS);
   370       if (col_iter_map.valid(col_it)) { //van hasznalhato hely
   371 	col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
   372 	col_iter_map[col_it]=i;
   373       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   374 	col_it=col_iter_map.push_back(i, VALID_CLASS);
   375       }
   376       return col_it;
   377     }
   378     /// \e
   379     RowIt addRow() {
   380       int i=_addRow();
   381       RowIt row_it;
   382       row_iter_map.first(row_it, INVALID_CLASS);
   383       if (row_iter_map.valid(row_it)) { //van hasznalhato hely
   384 	row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
   385 	row_iter_map[row_it]=i;
   386       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   387 	row_it=row_iter_map.push_back(i, VALID_CLASS);
   388       }
   389       return row_it;
   390     }
   391     /// \e
   392     void eraseCol(const ColIt& col_it) {
   393       col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
   394       int cols[2];
   395       cols[1]=col_iter_map[col_it];
   396       _eraseCol(cols[1]);
   397       col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
   398       ColIt it;
   399       for (col_iter_map.first(it, VALID_CLASS); 
   400 	   col_iter_map.valid(it); col_iter_map.next(it)) {
   401 	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
   402       }
   403     }
   404     /// \e
   405     void eraseRow(const RowIt& row_it) {
   406       row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
   407       int rows[2];
   408       rows[1]=row_iter_map[row_it];
   409       _eraseRow(rows[1]);
   410       row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
   411       RowIt it;
   412       for (row_iter_map.first(it, VALID_CLASS); 
   413 	   row_iter_map.valid(it); row_iter_map.next(it)) {
   414 	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
   415       }
   416     }
   417     /// \e
   418     template <typename Begin, typename End>
   419     void setRowCoeffs(RowIt row_it, Begin begin, End end) {
   420       std::vector<std::pair<int, double> > coeffs;
   421       for ( ; begin!=end; ++begin) {
   422 	coeffs.push_back(std::
   423 			 make_pair(col_iter_map[begin->first], begin->second));
   424       }
   425       _setRowCoeffs(row_iter_map[row_it], coeffs);
   426     }
   427     /// \e
   428     template <typename Begin, typename End>
   429     void setColCoeffs(ColIt col_it, Begin begin, End end) {
   430       std::vector<std::pair<int, double> > coeffs;
   431       for ( ; begin!=end; ++begin) {
   432 	coeffs.push_back(std::
   433 			 make_pair(row_iter_map[begin->first], begin->second));
   434       }
   435       _setColCoeffs(col_iter_map[col_it], coeffs);
   436     }
   437     /// \e
   438     void setColLowerBound(ColIt col_it, _Value lo) {
   439       _setColLowerBound(col_iter_map[col_it], lo);
   440     }
   441     /// \e
   442     _Value getColLowerBound(ColIt col_it) {
   443       return _getColLowerBound(col_iter_map[col_it]);
   444     }
   445     /// \e
   446     void setColUpperBound(ColIt col_it, _Value up) {
   447       _setColUpperBound(col_iter_map[col_it], up);
   448     }
   449     /// \e
   450     _Value getColUpperBound(ColIt col_it) {      
   451       return _getColUpperBound(col_iter_map[col_it]);
   452     }
   453     /// \e
   454     void setRowLowerBound(RowIt row_it, _Value lo) {
   455       _setRowLowerBound(row_iter_map[row_it], lo);
   456     }
   457     /// \e
   458     _Value getRowLowerBound(RowIt row_it) {
   459       return _getRowLowerBound(row_iter_map[row_it]);
   460     }
   461     /// \e
   462     void setRowUpperBound(RowIt row_it, _Value up) {
   463       _setRowUpperBound(row_iter_map[row_it], up);
   464     }
   465     /// \e
   466     _Value getRowUpperBound(RowIt row_it) {      
   467       return _getRowUpperBound(row_iter_map[row_it]);
   468     }
   469     /// \e
   470     void setObjCoef(const ColIt& col_it, _Value obj_coef) {
   471       _setObjCoef(col_iter_map[col_it], obj_coef);
   472     }
   473     /// \e
   474     _Value getObjCoef(const ColIt& col_it) {
   475       return _getObjCoef(col_iter_map[col_it]);
   476     }
   477 
   478     //SOLUTION RETRIEVING FUNCTIONS
   479 
   480     /// \e
   481     _Value getPrimal(const ColIt& col_it) {
   482       return _getPrimal(col_iter_map[col_it]);
   483     }    
   484 
   485     //@}
   486 
   487     /*! @name User friend interface
   488       Problem manipulating functions in the user friend interface
   489     */
   490     //@{
   491 
   492     //EXPRESSION TYPES
   493 
   494     /// \e
   495     typedef Expr<ColIt, _Value> Expression;
   496     /// \e
   497     typedef Expr<RowIt, _Value> DualExpression;
   498 
   499     //MATRIX MANIPULATING FUNCTIONS
   500 
   501     /// \e
   502     void setRowCoeffs(RowIt row_it, const Expression& expr) {
   503       std::vector<std::pair<int, _Value> > row_coeffs;
   504       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
   505 	  i!=expr.data.end(); ++i) {
   506 	row_coeffs.push_back(std::make_pair
   507 			     (col_iter_map[(*i).first], (*i).second));
   508       }
   509       _setRowCoeffs(row_iter_map[row_it], row_coeffs);
   510     }
   511     /// \e
   512     void setColCoeffs(ColIt col_it, const DualExpression& expr) {
   513       std::vector<std::pair<int, _Value> > col_coeffs;
   514       for(typename DualExpression::Data::const_iterator i=expr.data.begin(); 
   515 	  i!=expr.data.end(); ++i) {
   516 	col_coeffs.push_back(std::make_pair
   517 			     (row_iter_map[(*i).first], (*i).second));
   518       }
   519       _setColCoeffs(col_iter_map[col_it], col_coeffs);
   520     }
   521     /// \e
   522     void setObjCoeffs(const Expression& expr) {
   523       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
   524 	  i!=expr.data.end(); ++i) {
   525 	setObjCoef((*i).first, (*i).second);
   526       }
   527     }
   528     //@}
   529   };
   530   
   531   template <typename _Value>
   532   const _Value LPSolverBase<_Value>::INF=std::numeric_limits<_Value>::infinity();
   533 
   534 
   535   /// \brief Wrapper for GLPK solver
   536   /// 
   537   /// This class implements a lemon wrapper for GLPK.
   538   class LPGLPK : public LPSolverBase<double> {
   539   public:
   540     typedef LPSolverBase<double> Parent;
   541 
   542   public:
   543     /// \e
   544     LPX* lp;
   545 
   546   public:
   547     /// \e
   548     LPGLPK() : Parent(), 
   549 			lp(lpx_create_prob()) {
   550       lpx_set_int_parm(lp, LPX_K_DUAL, 1);
   551     }
   552     /// \e
   553     ~LPGLPK() {
   554       lpx_delete_prob(lp);
   555     }
   556 
   557     //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
   558 
   559     /// \e
   560     void setMinimize() { 
   561       lpx_set_obj_dir(lp, LPX_MIN);
   562     }
   563     /// \e
   564     void setMaximize() { 
   565       lpx_set_obj_dir(lp, LPX_MAX);
   566     }
   567 
   568     //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
   569 
   570   protected:
   571     /// \e
   572     int _addCol() { 
   573       int i=lpx_add_cols(lp, 1);
   574       _setColLowerBound(i, -INF);
   575       _setColUpperBound(i, INF);
   576       return i;
   577     }
   578     /// \e
   579     int _addRow() { 
   580       int i=lpx_add_rows(lp, 1);
   581       return i;
   582     }
   583     /// \e
   584     virtual void _setRowCoeffs(int i, 
   585 			       const std::vector<std::pair<int, double> >& coeffs) {
   586       int mem_length=1+colNum();
   587       int* indices = new int[mem_length];
   588       double* doubles = new double[mem_length];
   589       int length=0;
   590       for (std::vector<std::pair<int, double> >::
   591 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   592 	++length;
   593 	indices[length]=it->first;
   594 	doubles[length]=it->second;
   595 // 	std::cout << "  " << indices[length] << " " 
   596 // 		  << doubles[length] << std::endl;
   597       }
   598 //      std::cout << i << " " << length << std::endl;
   599       lpx_set_mat_row(lp, i, length, indices, doubles);
   600       delete [] indices;
   601       delete [] doubles;
   602     }
   603     /// \e
   604     virtual void _setColCoeffs(int i, 
   605 			       const std::vector<std::pair<int, double> >& coeffs) {
   606       int mem_length=1+rowNum();
   607       int* indices = new int[mem_length];
   608       double* doubles = new double[mem_length];
   609       int length=0;
   610       for (std::vector<std::pair<int, double> >::
   611 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   612 	++length;
   613 	indices[length]=it->first;
   614 	doubles[length]=it->second;
   615       }
   616       lpx_set_mat_col(lp, i, length, indices, doubles);
   617       delete [] indices;
   618       delete [] doubles;
   619     }
   620     /// \e
   621     virtual void _eraseCol(int i) {
   622       int cols[2];
   623       cols[1]=i;
   624       lpx_del_cols(lp, 1, cols);
   625     }
   626     virtual void _eraseRow(int i) {
   627       int rows[2];
   628       rows[1]=i;
   629       lpx_del_rows(lp, 1, rows);
   630     }
   631     virtual void _setColLowerBound(int i, double lo) {
   632       if (lo==INF) {
   633 	//FIXME error
   634       }
   635       int b=lpx_get_col_type(lp, i);
   636       double up=lpx_get_col_ub(lp, i);	
   637       if (lo==-INF) {
   638 	switch (b) {
   639 	case LPX_FR:
   640 	case LPX_LO:
   641 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   642 	  break;
   643 	case LPX_UP:
   644 	  break;
   645 	case LPX_DB:
   646 	case LPX_FX:
   647 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   648 	  break;
   649 	default: ;
   650 	  //FIXME error
   651 	}
   652       } else {
   653 	switch (b) {
   654 	case LPX_FR:
   655 	case LPX_LO:
   656 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   657 	  break;
   658 	case LPX_UP:	  
   659 	case LPX_DB:
   660 	case LPX_FX:
   661 	  if (lo==up) 
   662 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   663 	  else 
   664 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   665 	  break;
   666 	default: ;
   667 	  //FIXME error
   668 	}
   669       }
   670     }
   671     virtual double _getColLowerBound(int i) {
   672       int b=lpx_get_col_type(lp, i);
   673       switch (b) {
   674       case LPX_FR:
   675 	return -INF;
   676       case LPX_LO:
   677 	return lpx_get_col_lb(lp, i);
   678       case LPX_UP:
   679 	return -INF;
   680       case LPX_DB:
   681       case LPX_FX:
   682 	return lpx_get_col_lb(lp, i);
   683       default: ;
   684 	//FIXME error
   685 	return 0.0;
   686       }
   687     }
   688     virtual void _setColUpperBound(int i, double up) {
   689       if (up==-INF) {
   690 	//FIXME error
   691       }
   692       int b=lpx_get_col_type(lp, i);
   693       double lo=lpx_get_col_lb(lp, i);
   694       if (up==INF) {
   695 	switch (b) {
   696 	case LPX_FR:
   697 	case LPX_LO:
   698 	  break;
   699 	case LPX_UP:
   700 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   701 	  break;
   702 	case LPX_DB:
   703 	case LPX_FX:
   704 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   705 	  break;
   706 	default: ;
   707 	  //FIXME error
   708 	}
   709       } else {
   710 	switch (b) {
   711 	case LPX_FR:
   712 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   713 	case LPX_LO:
   714 	  if (lo==up) 
   715 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   716 	  else
   717 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   718 	  break;
   719 	case LPX_UP:
   720 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   721 	  break;
   722 	case LPX_DB:
   723 	case LPX_FX:
   724 	  if (lo==up) 
   725 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   726 	  else 
   727 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   728 	  break;
   729 	default: ;
   730 	  //FIXME error
   731 	}
   732       }
   733     }
   734     virtual double _getColUpperBound(int i) {
   735       int b=lpx_get_col_type(lp, i);
   736       switch (b) {
   737       case LPX_FR:
   738       case LPX_LO:
   739 	return INF;
   740       case LPX_UP:
   741       case LPX_DB:
   742       case LPX_FX:
   743 	return lpx_get_col_ub(lp, i);
   744       default: ;
   745 	//FIXME error
   746 	return 0.0;
   747       }
   748     }
   749     virtual void _setRowLowerBound(int i, double lo) {
   750       if (lo==INF) {
   751 	//FIXME error
   752       }
   753       int b=lpx_get_row_type(lp, i);
   754       double up=lpx_get_row_ub(lp, i);	
   755       if (lo==-INF) {
   756 	switch (b) {
   757 	case LPX_FR:
   758 	case LPX_LO:
   759 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
   760 	  break;
   761 	case LPX_UP:
   762 	  break;
   763 	case LPX_DB:
   764 	case LPX_FX:
   765 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   766 	  break;
   767 	default: ;
   768 	  //FIXME error
   769 	}
   770       } else {
   771 	switch (b) {
   772 	case LPX_FR:
   773 	case LPX_LO:
   774 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
   775 	  break;
   776 	case LPX_UP:	  
   777 	case LPX_DB:
   778 	case LPX_FX:
   779 	  if (lo==up) 
   780 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   781 	  else 
   782 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   783 	  break;
   784 	default: ;
   785 	  //FIXME error
   786 	}
   787       }
   788     }
   789     virtual double _getRowLowerBound(int i) {
   790       int b=lpx_get_row_type(lp, i);
   791       switch (b) {
   792       case LPX_FR:
   793 	return -INF;
   794       case LPX_LO:
   795 	return lpx_get_row_lb(lp, i);
   796       case LPX_UP:
   797 	return -INF;
   798       case LPX_DB:
   799       case LPX_FX:
   800 	return lpx_get_row_lb(lp, i);
   801       default: ;
   802 	//FIXME error
   803 	return 0.0;
   804       }
   805     }
   806     virtual void _setRowUpperBound(int i, double up) {
   807       if (up==-INF) {
   808 	//FIXME error
   809       }
   810       int b=lpx_get_row_type(lp, i);
   811       double lo=lpx_get_row_lb(lp, i);
   812       if (up==INF) {
   813 	switch (b) {
   814 	case LPX_FR:
   815 	case LPX_LO:
   816 	  break;
   817 	case LPX_UP:
   818 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
   819 	  break;
   820 	case LPX_DB:
   821 	case LPX_FX:
   822 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
   823 	  break;
   824 	default: ;
   825 	  //FIXME error
   826 	}
   827       } else {
   828 	switch (b) {
   829 	case LPX_FR:
   830 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   831 	case LPX_LO:
   832 	  if (lo==up) 
   833 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   834 	  else
   835 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   836 	  break;
   837 	case LPX_UP:
   838 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   839 	  break;
   840 	case LPX_DB:
   841 	case LPX_FX:
   842 	  if (lo==up) 
   843 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   844 	  else 
   845 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   846 	  break;
   847 	default: ;
   848 	  //FIXME error
   849 	}
   850       }
   851     }
   852     virtual double _getRowUpperBound(int i) {
   853       int b=lpx_get_row_type(lp, i);
   854       switch (b) {
   855       case LPX_FR:
   856       case LPX_LO:
   857 	return INF;
   858       case LPX_UP:
   859       case LPX_DB:
   860       case LPX_FX:
   861 	return lpx_get_row_ub(lp, i);
   862       default: ;
   863 	//FIXME error
   864 	return 0.0;
   865       }
   866     }
   867     /// \e
   868     virtual double _getObjCoef(int i) { 
   869       return lpx_get_obj_coef(lp, i);
   870     }
   871     /// \e
   872     virtual void _setObjCoef(int i, double obj_coef) { 
   873       lpx_set_obj_coef(lp, i, obj_coef);
   874     }
   875   public:
   876     /// \e
   877     void solveSimplex() { lpx_simplex(lp); }
   878     /// \e
   879     void solvePrimalSimplex() { lpx_simplex(lp); }
   880     /// \e
   881     void solveDualSimplex() { lpx_simplex(lp); }
   882     /// \e
   883   protected:
   884     virtual double _getPrimal(int i) {
   885       return lpx_get_col_prim(lp, i);
   886     }
   887   public:
   888     /// \e
   889     double getObjVal() { return lpx_get_obj_val(lp); }
   890     /// \e
   891     int rowNum() const { return lpx_get_num_rows(lp); }
   892     /// \e
   893     int colNum() const { return lpx_get_num_cols(lp); }
   894     /// \e
   895     int warmUp() { return lpx_warm_up(lp); }
   896     /// \e
   897     void printWarmUpStatus(int i) {
   898       switch (i) {
   899       case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
   900       case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
   901       case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
   902       case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
   903       }
   904     }
   905     /// \e
   906     int getPrimalStatus() { return lpx_get_prim_stat(lp); }
   907     /// \e
   908     void printPrimalStatus(int i) {
   909       switch (i) {
   910       case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
   911       case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
   912       case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
   913       case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
   914       }
   915     }
   916     /// \e
   917     int getDualStatus() { return lpx_get_dual_stat(lp); }
   918     /// \e
   919     void printDualStatus(int i) {
   920       switch (i) {
   921       case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
   922       case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
   923       case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
   924       case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
   925       }
   926     }
   927     /// Returns the status of the slack variable assigned to row \c row_it.
   928     int getRowStat(const RowIt& row_it) { 
   929       return lpx_get_row_stat(lp, row_iter_map[row_it]); 
   930     }
   931     /// \e
   932     void printRowStatus(int i) {
   933       switch (i) {
   934       case LPX_BS: cout << "LPX_BS" << endl; break;
   935       case LPX_NL: cout << "LPX_NL" << endl; break;	
   936       case LPX_NU: cout << "LPX_NU" << endl; break;
   937       case LPX_NF: cout << "LPX_NF" << endl; break;
   938       case LPX_NS: cout << "LPX_NS" << endl; break;
   939       }
   940     }
   941     /// Returns the status of the variable assigned to column \c col_it.
   942     int getColStat(const ColIt& col_it) { 
   943       return lpx_get_col_stat(lp, col_iter_map[col_it]); 
   944     }
   945     /// \e
   946     void printColStatus(int i) {
   947       switch (i) {
   948       case LPX_BS: cout << "LPX_BS" << endl; break;
   949       case LPX_NL: cout << "LPX_NL" << endl; break;	
   950       case LPX_NU: cout << "LPX_NU" << endl; break;
   951       case LPX_NF: cout << "LPX_NF" << endl; break;
   952       case LPX_NS: cout << "LPX_NS" << endl; break;
   953       }
   954     }
   955   };
   956   
   957   /// @}
   958 
   959 } //namespace lemon
   960 
   961 #endif //LEMON_LP_SOLVER_WRAPPER_H