src/work/marci/lp/lp_solver_base.h
author marci
Thu, 10 Feb 2005 18:53:30 +0000
changeset 1144 1cfabf245433
parent 1143 4fb22cfa5759
child 1152 1765ff9fefa1
permissions -rw-r--r--
trying to add constraints of kind 1 <= x[2]+x[3] <= 4
     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 Row;
   197     /// \e
   198     typedef IterablePartition<int>::ClassIt Col;
   199   public:
   200     /// \e
   201     IterablePartition<int> row_iter_map;
   202     /// \e
   203     IterablePartition<int> col_iter_map;
   204     /// \e
   205     std::vector<Row> int_row_map;
   206     /// \e
   207     std::vector<Col> 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.
   275     virtual int getRowStat(const Row& row) = 0;
   276     /// \e
   277     virtual void printRowStatus(int i) = 0;
   278     /// Returns the status of the variable assigned to column \c col.
   279     virtual int getColStat(const Col& col) = 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     Col addCol() {
   379       int i=_addCol();  
   380       Col col;
   381       col_iter_map.first(col, INVALID_CLASS);
   382       if (col_iter_map.valid(col)) { //van hasznalhato hely
   383 	col_iter_map.set(col, INVALID_CLASS, VALID_CLASS);
   384 	col_iter_map[col]=i;
   385       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   386 	col=col_iter_map.push_back(i, VALID_CLASS);
   387       }
   388       int_col_map.push_back(col);
   389       return col;
   390     }
   391     /// \e
   392     Row addRow() {
   393       int i=_addRow();
   394       Row row;
   395       row_iter_map.first(row, INVALID_CLASS);
   396       if (row_iter_map.valid(row)) { //van hasznalhato hely
   397 	row_iter_map.set(row, INVALID_CLASS, VALID_CLASS);
   398 	row_iter_map[row]=i;
   399       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
   400 	row=row_iter_map.push_back(i, VALID_CLASS);
   401       }
   402       int_row_map.push_back(row);
   403       return row;
   404     }
   405     /// \e
   406     void eraseCol(const Col& col) {
   407       col_iter_map.set(col, VALID_CLASS, INVALID_CLASS);
   408       int cols[2];
   409       cols[1]=col_iter_map[col];
   410       _eraseCol(cols[1]);
   411       col_iter_map[col]=0; //glpk specifikus, de kell ez??
   412       Col 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 Row& row) {
   421       row_iter_map.set(row, VALID_CLASS, INVALID_CLASS);
   422       int rows[2];
   423       rows[1]=row_iter_map[row];
   424       _eraseRow(rows[1]);
   425       row_iter_map[row]=0; //glpk specifikus, de kell ez??
   426       Row 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     void setColLowerBound(Col col, _Value lo) {
   435       _setColLowerBound(col_iter_map[col], lo);
   436     }
   437     /// \e
   438     _Value getColLowerBound(Col col) {
   439       return _getColLowerBound(col_iter_map[col]);
   440     }
   441     /// \e
   442     void setColUpperBound(Col col, _Value up) {
   443       _setColUpperBound(col_iter_map[col], up);
   444     }
   445     /// \e
   446     _Value getColUpperBound(Col col) {      
   447       return _getColUpperBound(col_iter_map[col]);
   448     }
   449     /// \e
   450     void setRowLowerBound(Row row, _Value lo) {
   451       _setRowLowerBound(row_iter_map[row], lo);
   452     }
   453     /// \e
   454     _Value getRowLowerBound(Row row) {
   455       return _getRowLowerBound(row_iter_map[row]);
   456     }
   457     /// \e
   458     void setRowUpperBound(Row row, _Value up) {
   459       _setRowUpperBound(row_iter_map[row], up);
   460     }
   461     /// \e
   462     _Value getRowUpperBound(Row row) {      
   463       return _getRowUpperBound(row_iter_map[row]);
   464     }
   465     /// \e
   466     void setObjCoef(const Col& col, _Value obj_coef) {
   467       _setObjCoef(col_iter_map[col], obj_coef);
   468     }
   469     /// \e
   470     _Value getObjCoef(const Col& col) {
   471       return _getObjCoef(col_iter_map[col]);
   472     }
   473 
   474     //SOLUTION RETRIEVING FUNCTIONS
   475 
   476     /// \e
   477     _Value getPrimal(const Col& col) {
   478       return _getPrimal(col_iter_map[col]);
   479     }    
   480 
   481     //@}
   482 
   483     /*! @name User friend interface
   484       Problem manipulating functions in the user friend interface
   485     */
   486     //@{
   487 
   488     //EXPRESSION TYPES
   489 
   490     /// \e
   491     typedef Expr<Col, _Value> Expression;
   492     /// \e
   493     typedef Expr<Row, _Value> DualExpression;
   494     /// \e
   495     typedef Constr<Col, _Value> Constraint;
   496 
   497     //MATRIX MANIPULATING FUNCTIONS
   498 
   499     /// \e
   500     void setRowCoeffs(Row row, const Expression& expr) {
   501       std::vector<std::pair<int, _Value> > row_coeffs;
   502       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
   503 	  i!=expr.data.end(); ++i) {
   504 	row_coeffs.push_back(std::make_pair
   505 			     (col_iter_map[(*i).first], (*i).second));
   506       }
   507       _setRowCoeffs(row_iter_map[row], row_coeffs);
   508     }
   509     /// \e 
   510     void setRow(Row row, const Constraint& constr) {
   511       setRowCoeffs(row, constr.expr);
   512       setRowLowerBound(row, constr.lo);
   513       setRowUpperBound(row, constr.up);
   514     }
   515     /// \e 
   516     Row addRow(const Constraint& constr) {
   517       Row row=addRow();
   518       setRowCoeffs(row, constr.expr);
   519       setRowLowerBound(row, constr.lo);
   520       setRowUpperBound(row, constr.up);
   521       return row;
   522     }
   523     /// \e
   524     /// This routine modifies \c expr by only adding to it.
   525     void getRowCoeffs(Row row, Expression& expr) {
   526       std::vector<std::pair<int, _Value> > row_coeffs;
   527       _getRowCoeffs(row_iter_map[row], row_coeffs);
   528       for(typename std::vector<std::pair<int, _Value> >::const_iterator 
   529  	    i=row_coeffs.begin(); i!=row_coeffs.end(); ++i) {
   530  	expr+= (*i).second*int_col_map[(*i).first];
   531       }
   532     }
   533     /// \e
   534     void setColCoeffs(Col col, const DualExpression& expr) {
   535       std::vector<std::pair<int, _Value> > col_coeffs;
   536       for(typename DualExpression::Data::const_iterator i=expr.data.begin(); 
   537 	  i!=expr.data.end(); ++i) {
   538 	col_coeffs.push_back(std::make_pair
   539 			     (row_iter_map[(*i).first], (*i).second));
   540       }
   541       _setColCoeffs(col_iter_map[col], col_coeffs);
   542     }
   543     /// \e
   544     /// This routine modifies \c expr by only adding to it.
   545     void getColCoeffs(Col col, DualExpression& expr) {
   546       std::vector<std::pair<int, _Value> > col_coeffs;
   547       _getColCoeffs(col_iter_map[col], col_coeffs);
   548       for(typename std::vector<std::pair<int, _Value> >::const_iterator 
   549  	    i=col_coeffs.begin(); i!=col_coeffs.end(); ++i) {
   550  	expr+= (*i).second*int_row_map[(*i).first];
   551       }
   552     }
   553     /// \e
   554     /// \bug ez igy nem jo
   555     void setObjCoeffs(const Expression& expr) {
   556       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
   557 	  i!=expr.data.end(); ++i) {
   558 	setObjCoef((*i).first, (*i).second);
   559       }
   560     }
   561     /// \e
   562     /// This routine modifies \c expr by only adding to it.
   563     void getObjCoeffs(Expression& expr) {
   564       /// FIXME not yet implemented
   565     }
   566     //@}
   567   };
   568   
   569   template <typename _Value>
   570   const _Value LPSolverBase<_Value>::INF=std::numeric_limits<_Value>::infinity();
   571 
   572 
   573   /// \brief Wrapper for GLPK solver
   574   /// 
   575   /// This class implements a lemon wrapper for GLPK.
   576   class LPGLPK : public LPSolverBase<double> {
   577   public:
   578     typedef LPSolverBase<double> Parent;
   579 
   580   public:
   581     /// \e
   582     LPX* lp;
   583 
   584   public:
   585     /// \e
   586     LPGLPK() : Parent(), 
   587 			lp(lpx_create_prob()) {
   588       int_row_map.push_back(Row());
   589       int_col_map.push_back(Col());
   590       lpx_set_int_parm(lp, LPX_K_DUAL, 1);
   591     }
   592     /// \e
   593     ~LPGLPK() {
   594       lpx_delete_prob(lp);
   595     }
   596 
   597     //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
   598 
   599     /// \e
   600     void setMinimize() { 
   601       lpx_set_obj_dir(lp, LPX_MIN);
   602     }
   603     /// \e
   604     void setMaximize() { 
   605       lpx_set_obj_dir(lp, LPX_MAX);
   606     }
   607 
   608     //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
   609 
   610   protected:
   611     /// \e
   612     int _addCol() { 
   613       int i=lpx_add_cols(lp, 1);
   614       _setColLowerBound(i, -INF);
   615       _setColUpperBound(i, INF);
   616       return i;
   617     }
   618     /// \e
   619     int _addRow() { 
   620       int i=lpx_add_rows(lp, 1);
   621       return i;
   622     }
   623     /// \e
   624     virtual void _setRowCoeffs(int i, 
   625 			       const std::vector<std::pair<int, double> >& coeffs) {
   626       int mem_length=1+colNum();
   627       int* indices = new int[mem_length];
   628       double* doubles = new double[mem_length];
   629       int length=0;
   630       for (std::vector<std::pair<int, double> >::
   631 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   632 	++length;
   633 	indices[length]=it->first;
   634 	doubles[length]=it->second;
   635       }
   636       lpx_set_mat_row(lp, i, length, indices, doubles);
   637       delete [] indices;
   638       delete [] doubles;
   639     }
   640     /// \e
   641     virtual void _getRowCoeffs(int i, 
   642 			       std::vector<std::pair<int, double> >& coeffs) {
   643       int mem_length=1+colNum();
   644       int* indices = new int[mem_length];
   645       double* doubles = new double[mem_length];
   646       int length=lpx_get_mat_row(lp, i, indices, doubles);
   647       for (int i=1; i<=length; ++i) {
   648 	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
   649       }
   650       delete [] indices;
   651       delete [] doubles;
   652     }
   653     /// \e
   654     virtual void _setColCoeffs(int i, 
   655 			       const std::vector<std::pair<int, double> >& coeffs) {
   656       int mem_length=1+rowNum();
   657       int* indices = new int[mem_length];
   658       double* doubles = new double[mem_length];
   659       int length=0;
   660       for (std::vector<std::pair<int, double> >::
   661 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
   662 	++length;
   663 	indices[length]=it->first;
   664 	doubles[length]=it->second;
   665       }
   666       lpx_set_mat_col(lp, i, length, indices, doubles);
   667       delete [] indices;
   668       delete [] doubles;
   669     }
   670     /// \e
   671     virtual void _getColCoeffs(int i, 
   672 			       std::vector<std::pair<int, double> >& coeffs) {
   673       int mem_length=1+rowNum();
   674       int* indices = new int[mem_length];
   675       double* doubles = new double[mem_length];
   676       int length=lpx_get_mat_col(lp, i, indices, doubles);
   677       for (int i=1; i<=length; ++i) {
   678 	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
   679       }
   680       delete [] indices;
   681       delete [] doubles;
   682     }
   683     /// \e
   684     virtual void _eraseCol(int i) {
   685       int cols[2];
   686       cols[1]=i;
   687       lpx_del_cols(lp, 1, cols);
   688     }
   689     virtual void _eraseRow(int i) {
   690       int rows[2];
   691       rows[1]=i;
   692       lpx_del_rows(lp, 1, rows);
   693     }
   694     virtual void _setColLowerBound(int i, double lo) {
   695       if (lo==INF) {
   696 	//FIXME error
   697       }
   698       int b=lpx_get_col_type(lp, i);
   699       double up=lpx_get_col_ub(lp, i);	
   700       if (lo==-INF) {
   701 	switch (b) {
   702 	case LPX_FR:
   703 	case LPX_LO:
   704 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   705 	  break;
   706 	case LPX_UP:
   707 	  break;
   708 	case LPX_DB:
   709 	case LPX_FX:
   710 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   711 	  break;
   712 	default: ;
   713 	  //FIXME error
   714 	}
   715       } else {
   716 	switch (b) {
   717 	case LPX_FR:
   718 	case LPX_LO:
   719 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   720 	  break;
   721 	case LPX_UP:	  
   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 _getColLowerBound(int i) {
   735       int b=lpx_get_col_type(lp, i);
   736       switch (b) {
   737       case LPX_FR:
   738 	return -INF;
   739       case LPX_LO:
   740 	return lpx_get_col_lb(lp, i);
   741       case LPX_UP:
   742 	return -INF;
   743       case LPX_DB:
   744       case LPX_FX:
   745 	return lpx_get_col_lb(lp, i);
   746       default: ;
   747 	//FIXME error
   748 	return 0.0;
   749       }
   750     }
   751     virtual void _setColUpperBound(int i, double up) {
   752       if (up==-INF) {
   753 	//FIXME error
   754       }
   755       int b=lpx_get_col_type(lp, i);
   756       double lo=lpx_get_col_lb(lp, i);
   757       if (up==INF) {
   758 	switch (b) {
   759 	case LPX_FR:
   760 	case LPX_LO:
   761 	  break;
   762 	case LPX_UP:
   763 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
   764 	  break;
   765 	case LPX_DB:
   766 	case LPX_FX:
   767 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
   768 	  break;
   769 	default: ;
   770 	  //FIXME error
   771 	}
   772       } else {
   773 	switch (b) {
   774 	case LPX_FR:
   775 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   776 	case LPX_LO:
   777 	  if (lo==up) 
   778 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   779 	  else
   780 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   781 	  break;
   782 	case LPX_UP:
   783 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
   784 	  break;
   785 	case LPX_DB:
   786 	case LPX_FX:
   787 	  if (lo==up) 
   788 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
   789 	  else 
   790 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
   791 	  break;
   792 	default: ;
   793 	  //FIXME error
   794 	}
   795       }
   796     }
   797     virtual double _getColUpperBound(int i) {
   798       int b=lpx_get_col_type(lp, i);
   799       switch (b) {
   800       case LPX_FR:
   801       case LPX_LO:
   802 	return INF;
   803       case LPX_UP:
   804       case LPX_DB:
   805       case LPX_FX:
   806 	return lpx_get_col_ub(lp, i);
   807       default: ;
   808 	//FIXME error
   809 	return 0.0;
   810       }
   811     }
   812     virtual void _setRowLowerBound(int i, double lo) {
   813       if (lo==INF) {
   814 	//FIXME error
   815       }
   816       int b=lpx_get_row_type(lp, i);
   817       double up=lpx_get_row_ub(lp, i);	
   818       if (lo==-INF) {
   819 	switch (b) {
   820 	case LPX_FR:
   821 	case LPX_LO:
   822 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
   823 	  break;
   824 	case LPX_UP:
   825 	  break;
   826 	case LPX_DB:
   827 	case LPX_FX:
   828 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   829 	  break;
   830 	default: ;
   831 	  //FIXME error
   832 	}
   833       } else {
   834 	switch (b) {
   835 	case LPX_FR:
   836 	case LPX_LO:
   837 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
   838 	  break;
   839 	case LPX_UP:	  
   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 _getRowLowerBound(int i) {
   853       int b=lpx_get_row_type(lp, i);
   854       switch (b) {
   855       case LPX_FR:
   856 	return -INF;
   857       case LPX_LO:
   858 	return lpx_get_row_lb(lp, i);
   859       case LPX_UP:
   860 	return -INF;
   861       case LPX_DB:
   862       case LPX_FX:
   863 	return lpx_get_row_lb(lp, i);
   864       default: ;
   865 	//FIXME error
   866 	return 0.0;
   867       }
   868     }
   869     virtual void _setRowUpperBound(int i, double up) {
   870       if (up==-INF) {
   871 	//FIXME error
   872       }
   873       int b=lpx_get_row_type(lp, i);
   874       double lo=lpx_get_row_lb(lp, i);
   875       if (up==INF) {
   876 	switch (b) {
   877 	case LPX_FR:
   878 	case LPX_LO:
   879 	  break;
   880 	case LPX_UP:
   881 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
   882 	  break;
   883 	case LPX_DB:
   884 	case LPX_FX:
   885 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
   886 	  break;
   887 	default: ;
   888 	  //FIXME error
   889 	}
   890       } else {
   891 	switch (b) {
   892 	case LPX_FR:
   893 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   894 	case LPX_LO:
   895 	  if (lo==up) 
   896 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   897 	  else
   898 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   899 	  break;
   900 	case LPX_UP:
   901 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
   902 	  break;
   903 	case LPX_DB:
   904 	case LPX_FX:
   905 	  if (lo==up) 
   906 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
   907 	  else 
   908 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
   909 	  break;
   910 	default: ;
   911 	  //FIXME error
   912 	}
   913       }
   914     }
   915     virtual double _getRowUpperBound(int i) {
   916       int b=lpx_get_row_type(lp, i);
   917       switch (b) {
   918       case LPX_FR:
   919       case LPX_LO:
   920 	return INF;
   921       case LPX_UP:
   922       case LPX_DB:
   923       case LPX_FX:
   924 	return lpx_get_row_ub(lp, i);
   925       default: ;
   926 	//FIXME error
   927 	return 0.0;
   928       }
   929     }
   930     /// \e
   931     virtual double _getObjCoef(int i) { 
   932       return lpx_get_obj_coef(lp, i);
   933     }
   934     /// \e
   935     virtual void _setObjCoef(int i, double obj_coef) { 
   936       lpx_set_obj_coef(lp, i, obj_coef);
   937     }
   938   public:
   939     /// \e
   940     void solveSimplex() { lpx_simplex(lp); }
   941     /// \e
   942     void solvePrimalSimplex() { lpx_simplex(lp); }
   943     /// \e
   944     void solveDualSimplex() { lpx_simplex(lp); }
   945     /// \e
   946   protected:
   947     virtual double _getPrimal(int i) {
   948       return lpx_get_col_prim(lp, i);
   949     }
   950   public:
   951     /// \e
   952     double getObjVal() { return lpx_get_obj_val(lp); }
   953     /// \e
   954     int rowNum() const { return lpx_get_num_rows(lp); }
   955     /// \e
   956     int colNum() const { return lpx_get_num_cols(lp); }
   957     /// \e
   958     int warmUp() { return lpx_warm_up(lp); }
   959     /// \e
   960     void printWarmUpStatus(int i) {
   961       switch (i) {
   962       case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
   963       case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
   964       case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
   965       case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
   966       }
   967     }
   968     /// \e
   969     int getPrimalStatus() { return lpx_get_prim_stat(lp); }
   970     /// \e
   971     void printPrimalStatus(int i) {
   972       switch (i) {
   973       case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
   974       case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
   975       case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
   976       case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
   977       }
   978     }
   979     /// \e
   980     int getDualStatus() { return lpx_get_dual_stat(lp); }
   981     /// \e
   982     void printDualStatus(int i) {
   983       switch (i) {
   984       case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
   985       case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
   986       case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
   987       case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
   988       }
   989     }
   990     /// Returns the status of the slack variable assigned to row \c row.
   991     int getRowStat(const Row& row) { 
   992       return lpx_get_row_stat(lp, row_iter_map[row]); 
   993     }
   994     /// \e
   995     void printRowStatus(int i) {
   996       switch (i) {
   997       case LPX_BS: cout << "LPX_BS" << endl; break;
   998       case LPX_NL: cout << "LPX_NL" << endl; break;	
   999       case LPX_NU: cout << "LPX_NU" << endl; break;
  1000       case LPX_NF: cout << "LPX_NF" << endl; break;
  1001       case LPX_NS: cout << "LPX_NS" << endl; break;
  1002       }
  1003     }
  1004     /// Returns the status of the variable assigned to column \c col.
  1005     int getColStat(const Col& col) { 
  1006       return lpx_get_col_stat(lp, col_iter_map[col]); 
  1007     }
  1008     /// \e
  1009     void printColStatus(int i) {
  1010       switch (i) {
  1011       case LPX_BS: cout << "LPX_BS" << endl; break;
  1012       case LPX_NL: cout << "LPX_NL" << endl; break;	
  1013       case LPX_NU: cout << "LPX_NU" << endl; break;
  1014       case LPX_NF: cout << "LPX_NF" << endl; break;
  1015       case LPX_NS: cout << "LPX_NS" << endl; break;
  1016       }
  1017     }
  1018   };
  1019   
  1020   /// @}
  1021 
  1022 } //namespace lemon
  1023 
  1024 #endif //LEMON_LP_SOLVER_WRAPPER_H