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