2 #ifndef LEMON_LP_SOLVER_BASE_H
 
     3 #define LEMON_LP_SOLVER_BASE_H
 
    26 #include <lemon/invalid.h>
 
    27 #include <expression.h>
 
    29 //#include <lemon/max_flow.h>
 
    30 //#include <augmenting_flow.h>
 
    31 //#include <iter_map.h>
 
    42   /// \brief A partitioned vector with iterable classes.
 
    44   /// This class implements a container in which the data is stored in an 
 
    45   /// stl vector, the range is partitioned into sets and each set is 
 
    46   /// doubly linked in a list. 
 
    47   /// That is, each class is iterable by lemon iterators, and any member of 
 
    48   /// the vector can bo moved to an other class.
 
    50   class IterablePartition {
 
    54       int prev; //invalid az -1
 
    57     std::vector<Node> nodes;
 
    62     std::vector<Tip> tips;
 
    64     /// The classes are indexed by integers from \c 0 to \c classNum()-1.
 
    65     int classNum() const { return tips.size(); }
 
    66     /// This lemon style iterator iterates through a class. 
 
    68     /// Constructor. The number of classes is to be given which is fixed 
 
    69     /// over the life of the container. 
 
    70     /// The partition classes are indexed from 0 to class_num-1. 
 
    71     IterablePartition(int class_num) { 
 
    72       for (int i=0; i<class_num; ++i) {
 
    79     void befuz(Class it, int class_id) {
 
    80       if (tips[class_id].first==-1) {
 
    81 	if (tips[class_id].last==-1) {
 
    82 	  nodes[it.i].prev=nodes[it.i].next=-1;
 
    83 	  tips[class_id].first=tips[class_id].last=it.i;
 
    86 	nodes[it.i].prev=tips[class_id].last;
 
    88 	nodes[tips[class_id].last].next=it.i;
 
    89 	tips[class_id].last=it.i;
 
    92     void kifuz(Class it, int class_id) {
 
    93       if (tips[class_id].first==it.i) {
 
    94 	if (tips[class_id].last==it.i) {
 
    95 	  tips[class_id].first=tips[class_id].last=-1;
 
    97 	  tips[class_id].first=nodes[it.i].next;
 
    98 	  nodes[nodes[it.i].next].prev=-1;
 
   101 	if (tips[class_id].last==it.i) {
 
   102 	  tips[class_id].last=nodes[it.i].prev;
 
   103 	  nodes[nodes[it.i].prev].next=-1;
 
   105 	  nodes[nodes[it.i].next].prev=nodes[it.i].prev;
 
   106 	  nodes[nodes[it.i].prev].next=nodes[it.i].next;
 
   111     /// A new element with data \c t is pushed into the vector and into class 
 
   113     Class push_back(const T& t, int class_id) { 
 
   117       int i=nodes.size()-1;
 
   121     /// A member is moved to an other class.
 
   122     void set(Class it, int old_class_id, int new_class_id) {
 
   123       kifuz(it.i, old_class_id);
 
   124       befuz(it.i, new_class_id);
 
   126     /// Returns the data pointed by \c it.
 
   127     T& operator[](Class it) { return nodes[it.i].data; }
 
   128     /// Returns the data pointed by \c it.
 
   129     const T& operator[](Class it) const { return nodes[it.i].data; }
 
   132       friend class IterablePartition;
 
   136       /// Default constructor.
 
   138       /// This constructor constructs an iterator which points
 
   139       /// to the member of th container indexed by the integer _i.
 
   140       Class(const int& _i) : i(_i) { }
 
   141       /// Invalid constructor.
 
   142       Class(const Invalid&) : i(-1) { }
 
   143       friend bool operator<(const Class& x, const Class& y);
 
   144       friend std::ostream& operator<<(std::ostream& os, 
 
   146       bool operator==(const Class& node) const {return i == node.i;}
 
   147       bool operator!=(const Class& node) const {return i != node.i;}
 
   149     friend bool operator<(const Class& x, const Class& y) {
 
   152     friend std::ostream& operator<<(std::ostream& os, 
 
   157     /// First member of class \c class_id.
 
   158     Class& first(Class& it, int class_id) const {
 
   159       it.i=tips[class_id].first;
 
   163     Class& next(Class& it) const {
 
   164       it.i=nodes[it.i].next;
 
   167     /// True iff the iterator is valid.
 
   168     bool valid(const Class& it) const { return it.i!=-1; }
 
   170     class ClassIt : public Class {
 
   171       const IterablePartition* iterable_partition;
 
   174       ClassIt(Invalid i) : Class(i) { }
 
   175       ClassIt(const IterablePartition& _iterable_partition, 
 
   176 	      const int& i) : iterable_partition(&_iterable_partition) {
 
   177         _iterable_partition.first(*this, i);
 
   179       ClassIt(const IterablePartition& _iterable_partition, 
 
   180 	      const Class& _class) : 
 
   181 	Class(_class), iterable_partition(&_iterable_partition) { }
 
   182       ClassIt& operator++() {
 
   183         iterable_partition->next(*this);
 
   192     \todo kellenene uj iterable structure bele, mert ez nem az igazi
 
   193     \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
 
   194     \todo LEKERDEZESEK!!!
 
   195     \todo DOKSI!!!! Doxygen group!!!
 
   196     The aim of this class is to give a general surface to different 
 
   197     solvers, i.e. it makes possible to write algorithms using LP's, 
 
   198     in which the solver can be changed to an other one easily.
 
   201   template <typename _Value>
 
   204     /*! @name Uncategorized functions and types (public members)
 
   212     typedef IterablePartition<int> Rows;
 
   214     typedef IterablePartition<int> Cols;
 
   216     typedef _Value Value;
 
   218     typedef Rows::Class Row;
 
   220     typedef Cols::Class Col;
 
   223     IterablePartition<int> row_iter_map;
 
   225     IterablePartition<int> col_iter_map;
 
   227     std::vector<Row> int_row_map;
 
   229     std::vector<Col> int_col_map;
 
   231     const int VALID_CLASS;
 
   233     const int INVALID_CLASS;
 
   235     static const _Value INF;
 
   238     LPSolverBase() : row_iter_map(2), 
 
   240 		     VALID_CLASS(0), INVALID_CLASS(1) { }
 
   242     virtual ~LPSolverBase() { }
 
   245     /*! @name Medium level interface (public members)
 
   246       These functions appear in the low level and also in the high level 
 
   247       interfaces thus these each of these functions have to be implemented 
 
   248       only once in the different interfaces.
 
   249       This means that these functions have to be reimplemented for all of the 
 
   250       different lp solvers. These are basic functions, and have the same 
 
   251       parameter lists in the low and high level interfaces. 
 
   256     //UNCATEGORIZED FUNCTIONS
 
   259     virtual void setMinimize() = 0;
 
   261     virtual void setMaximize() = 0;
 
   266     virtual void solveSimplex() = 0;
 
   268     virtual void solvePrimalSimplex() = 0;
 
   270     virtual void solveDualSimplex() = 0;
 
   272     //SOLUTION RETRIEVING
 
   275     virtual _Value getObjVal() = 0;
 
   280     virtual int rowNum() const = 0;
 
   282     virtual int colNum() const = 0;
 
   284     virtual int warmUp() = 0;
 
   286     virtual void printWarmUpStatus(int i) = 0;
 
   288     virtual int getPrimalStatus() = 0;
 
   290     virtual void printPrimalStatus(int i) = 0;
 
   292     virtual int getDualStatus() = 0;
 
   294     virtual void printDualStatus(int i) = 0;
 
   295     /// Returns the status of the slack variable assigned to row \c row.
 
   296     virtual int getRowStat(const Row& row) = 0;
 
   298     virtual void printRowStatus(int i) = 0;
 
   299     /// Returns the status of the variable assigned to column \c col.
 
   300     virtual int getColStat(const Col& col) = 0;
 
   302     virtual void printColStatus(int i) = 0;
 
   306     /*! @name Low level interface (protected members)
 
   307       Problem manipulating functions in the low level interface
 
   312     //MATRIX MANIPULATING FUNCTIONS
 
   315     virtual int _addCol() = 0;
 
   317     virtual int _addRow() = 0;
 
   319     virtual void _eraseCol(int i) = 0;
 
   321     virtual void _eraseRow(int i) = 0;
 
   323     virtual void _setRowCoeffs(int i, 
 
   324 			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
 
   326     /// This routine modifies \c coeffs only by the \c push_back method.
 
   327     virtual void _getRowCoeffs(int i, 
 
   328 			       std::vector<std::pair<int, _Value> >& coeffs) = 0;
 
   330     virtual void _setColCoeffs(int i, 
 
   331 			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
 
   333     /// This routine modifies \c coeffs only by the \c push_back method.
 
   334     virtual void _getColCoeffs(int i, 
 
   335 			       std::vector<std::pair<int, _Value> >& coeffs) = 0;
 
   337     virtual void _setCoeff(int col, int row, _Value value) = 0;
 
   339     virtual _Value _getCoeff(int col, int row) = 0;
 
   342     //    enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
 
   345     /// The lower bound of a variable (column) have to be given by an 
 
   346     /// extended number of type _Value, i.e. a finite number of type 
 
   348     virtual void _setColLowerBound(int i, _Value value) = 0;
 
   350     /// The lower bound of a variable (column) is an 
 
   351     /// extended number of type _Value, i.e. a finite number of type 
 
   353     virtual _Value _getColLowerBound(int i) = 0;
 
   355     /// The upper bound of a variable (column) have to be given by an 
 
   356     /// extended number of type _Value, i.e. a finite number of type 
 
   358     virtual void _setColUpperBound(int i, _Value value) = 0;
 
   360     /// The upper bound of a variable (column) is an 
 
   361     /// extended number of type _Value, i.e. a finite number of type 
 
   363     virtual _Value _getColUpperBound(int i) = 0;
 
   365     /// The lower bound of a linear expression (row) have to be given by an 
 
   366     /// extended number of type _Value, i.e. a finite number of type 
 
   368     virtual void _setRowLowerBound(int i, _Value value) = 0;
 
   370     /// The lower bound of a linear expression (row) is an 
 
   371     /// extended number of type _Value, i.e. a finite number of type 
 
   373     virtual _Value _getRowLowerBound(int i) = 0;
 
   375     /// The upper bound of a linear expression (row) have to be given by an 
 
   376     /// extended number of type _Value, i.e. a finite number of type 
 
   378     virtual void _setRowUpperBound(int i, _Value value) = 0;
 
   380     /// The upper bound of a linear expression (row) is an 
 
   381     /// extended number of type _Value, i.e. a finite number of type 
 
   383     virtual _Value _getRowUpperBound(int i) = 0;
 
   385     virtual void _setObjCoeff(int i, _Value obj_coef) = 0;
 
   387     virtual _Value _getObjCoeff(int i) = 0;
 
   389     //SOLUTION RETRIEVING
 
   392     virtual _Value _getPrimal(int i) = 0;
 
   395     /*! @name High level interface (public members)
 
   396       Problem manipulating functions in the high level interface
 
   401     //MATRIX MANIPULATING FUNCTIONS
 
   407       col_iter_map.first(col, INVALID_CLASS);
 
   408       if (col_iter_map.valid(col)) { //van hasznalhato hely
 
   409 	col_iter_map.set(col, INVALID_CLASS, VALID_CLASS);
 
   411       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
 
   412 	col=col_iter_map.push_back(i, VALID_CLASS);
 
   414       int_col_map.push_back(col);
 
   421       row_iter_map.first(row, INVALID_CLASS);
 
   422       if (row_iter_map.valid(row)) { //van hasznalhato hely
 
   423 	row_iter_map.set(row, INVALID_CLASS, VALID_CLASS);
 
   425       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
 
   426 	row=row_iter_map.push_back(i, VALID_CLASS);
 
   428       int_row_map.push_back(row);
 
   432     void eraseCol(const Col& col) {
 
   433       col_iter_map.set(col, VALID_CLASS, INVALID_CLASS);
 
   435       cols[1]=col_iter_map[col];
 
   437       col_iter_map[col]=0; //glpk specifikus, de kell ez??
 
   439       for (col_iter_map.first(it, VALID_CLASS); 
 
   440 	   col_iter_map.valid(it); col_iter_map.next(it)) {
 
   441 	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
 
   443       int_col_map.erase(int_col_map.begin()+cols[1]);
 
   446     void eraseRow(const Row& row) {
 
   447       row_iter_map.set(row, VALID_CLASS, INVALID_CLASS);
 
   449       rows[1]=row_iter_map[row];
 
   451       row_iter_map[row]=0; //glpk specifikus, de kell ez??
 
   453       for (row_iter_map.first(it, VALID_CLASS); 
 
   454 	   row_iter_map.valid(it); row_iter_map.next(it)) {
 
   455 	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
 
   457       int_row_map.erase(int_row_map.begin()+rows[1]);
 
   460     void setCoeff(Col col, Row row, _Value value) {
 
   461       _setCoeff(col_iter_map[col], row_iter_map[row], value);
 
   464     _Value getCoeff(Col col, Row row) {
 
   465       return _getCoeff(col_iter_map[col], row_iter_map[row], value);
 
   468     void setColLowerBound(Col col, _Value lo) {
 
   469       _setColLowerBound(col_iter_map[col], lo);
 
   472     _Value getColLowerBound(Col col) {
 
   473       return _getColLowerBound(col_iter_map[col]);
 
   476     void setColUpperBound(Col col, _Value up) {
 
   477       _setColUpperBound(col_iter_map[col], up);
 
   480     _Value getColUpperBound(Col col) {      
 
   481       return _getColUpperBound(col_iter_map[col]);
 
   484     void setRowLowerBound(Row row, _Value lo) {
 
   485       _setRowLowerBound(row_iter_map[row], lo);
 
   488     _Value getRowLowerBound(Row row) {
 
   489       return _getRowLowerBound(row_iter_map[row]);
 
   492     void setRowUpperBound(Row row, _Value up) {
 
   493       _setRowUpperBound(row_iter_map[row], up);
 
   496     _Value getRowUpperBound(Row row) {      
 
   497       return _getRowUpperBound(row_iter_map[row]);
 
   500     void setObjCoeff(const Col& col, _Value obj_coef) {
 
   501       _setObjCoeff(col_iter_map[col], obj_coef);
 
   504     _Value getObjCoeff(const Col& col) {
 
   505       return _getObjCoeff(col_iter_map[col]);
 
   508     //SOLUTION RETRIEVING FUNCTIONS
 
   511     _Value getPrimal(const Col& col) {
 
   512       return _getPrimal(col_iter_map[col]);
 
   517     /*! @name User friend interface
 
   518       Problem manipulating functions in the user friend interface
 
   525     typedef Expr<Col, _Value> Expression;
 
   527     typedef Expr<Row, _Value> DualExpression;
 
   529     typedef Constr<Col, _Value> Constraint;
 
   531     //MATRIX MANIPULATING FUNCTIONS
 
   534     void setRowCoeffs(Row row, const Expression& expr) {
 
   535       std::vector<std::pair<int, _Value> > row_coeffs;
 
   536       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
 
   537 	  i!=expr.data.end(); ++i) {
 
   538 	row_coeffs.push_back(std::make_pair
 
   539 			     (col_iter_map[(*i).first], (*i).second));
 
   541       _setRowCoeffs(row_iter_map[row], row_coeffs);
 
   544     void setRow(Row row, const Constraint& constr) {
 
   545       setRowCoeffs(row, constr.expr);
 
   546       setRowLowerBound(row, constr.lo);
 
   547       setRowUpperBound(row, constr.up);
 
   550     Row addRow(const Constraint& constr) {
 
   552       setRowCoeffs(row, constr.expr);
 
   553       setRowLowerBound(row, constr.lo);
 
   554       setRowUpperBound(row, constr.up);
 
   558     /// This routine modifies \c expr by only adding to it.
 
   559     void getRowCoeffs(Row row, Expression& expr) {
 
   560       std::vector<std::pair<int, _Value> > row_coeffs;
 
   561       _getRowCoeffs(row_iter_map[row], row_coeffs);
 
   562       for(typename std::vector<std::pair<int, _Value> >::const_iterator 
 
   563  	    i=row_coeffs.begin(); i!=row_coeffs.end(); ++i) {
 
   564  	expr+= (*i).second*int_col_map[(*i).first];
 
   568     void setColCoeffs(Col col, const DualExpression& expr) {
 
   569       std::vector<std::pair<int, _Value> > col_coeffs;
 
   570       for(typename DualExpression::Data::const_iterator i=expr.data.begin(); 
 
   571 	  i!=expr.data.end(); ++i) {
 
   572 	col_coeffs.push_back(std::make_pair
 
   573 			     (row_iter_map[(*i).first], (*i).second));
 
   575       _setColCoeffs(col_iter_map[col], col_coeffs);
 
   578     /// This routine modifies \c expr by only adding to it.
 
   579     void getColCoeffs(Col col, DualExpression& expr) {
 
   580       std::vector<std::pair<int, _Value> > col_coeffs;
 
   581       _getColCoeffs(col_iter_map[col], col_coeffs);
 
   582       for(typename std::vector<std::pair<int, _Value> >::const_iterator 
 
   583  	    i=col_coeffs.begin(); i!=col_coeffs.end(); ++i) {
 
   584  	expr+= (*i).second*int_row_map[(*i).first];
 
   588     void setObjCoeffs(const Expression& expr) {
 
   589       // writing zero everywhere
 
   590       for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
 
   591 	setObjCoeff(it, 0.0);
 
   592       // writing the data needed
 
   593       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
 
   594 	  i!=expr.data.end(); ++i) {
 
   595 	setObjCoeff((*i).first, (*i).second);
 
   599     /// This routine modifies \c expr by only adding to it.
 
   600     void getObjCoeffs(Expression& expr) {
 
   601       for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
 
   602 	expr+=getObjCoeff(it)*it;
 
   607     /*! @name MIP functions and types (public members)
 
   612     virtual void solveBandB() = 0;
 
   614     virtual void setLP() = 0;
 
   616     virtual void setMIP() = 0;
 
   619     virtual void _setColCont(int i) = 0;
 
   621     virtual void _setColInt(int i) = 0;
 
   623     virtual _Value _getMIPPrimal(int i) = 0;
 
   626     void setColCont(Col col) {
 
   627       _setColCont(col_iter_map[col]);
 
   630     void setColInt(Col col) {
 
   631       _setColInt(col_iter_map[col]);
 
   634     _Value getMIPPrimal(Col col) {
 
   635       return _getMIPPrimal(col_iter_map[col]);
 
   640   template <typename _Value>
 
   641   const _Value LPSolverBase<_Value>::INF=std::numeric_limits<_Value>::infinity();
 
   644   /// \brief Wrapper for GLPK solver
 
   646   /// This class implements a lemon wrapper for GLPK.
 
   647   class LPGLPK : public LPSolverBase<double> {
 
   649     typedef LPSolverBase<double> Parent;
 
   658 			lp(lpx_create_prob()) {
 
   659       int_row_map.push_back(Row());
 
   660       int_col_map.push_back(Col());
 
   661       lpx_set_int_parm(lp, LPX_K_DUAL, 1);
 
   668     //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
 
   672       lpx_set_obj_dir(lp, LPX_MIN);
 
   676       lpx_set_obj_dir(lp, LPX_MAX);
 
   679     //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
 
   684       int i=lpx_add_cols(lp, 1);
 
   685       _setColLowerBound(i, -INF);
 
   686       _setColUpperBound(i, INF);
 
   691       int i=lpx_add_rows(lp, 1);
 
   695     virtual void _setRowCoeffs(int i, 
 
   696 			       const std::vector<std::pair<int, double> >& coeffs) {
 
   697       int mem_length=1+colNum();
 
   698       int* indices = new int[mem_length];
 
   699       double* doubles = new double[mem_length];
 
   701       for (std::vector<std::pair<int, double> >::
 
   702 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
 
   704 	indices[length]=it->first;
 
   705 	doubles[length]=it->second;
 
   707       lpx_set_mat_row(lp, i, length, indices, doubles);
 
   712     virtual void _getRowCoeffs(int i, 
 
   713 			       std::vector<std::pair<int, double> >& coeffs) {
 
   714       int mem_length=1+colNum();
 
   715       int* indices = new int[mem_length];
 
   716       double* doubles = new double[mem_length];
 
   717       int length=lpx_get_mat_row(lp, i, indices, doubles);
 
   718       for (int i=1; i<=length; ++i) {
 
   719 	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
 
   725     virtual void _setColCoeffs(int i, 
 
   726 			       const std::vector<std::pair<int, double> >& coeffs) {
 
   727       int mem_length=1+rowNum();
 
   728       int* indices = new int[mem_length];
 
   729       double* doubles = new double[mem_length];
 
   731       for (std::vector<std::pair<int, double> >::
 
   732 	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
 
   734 	indices[length]=it->first;
 
   735 	doubles[length]=it->second;
 
   737       lpx_set_mat_col(lp, i, length, indices, doubles);
 
   742     virtual void _getColCoeffs(int i, 
 
   743 			       std::vector<std::pair<int, double> >& coeffs) {
 
   744       int mem_length=1+rowNum();
 
   745       int* indices = new int[mem_length];
 
   746       double* doubles = new double[mem_length];
 
   747       int length=lpx_get_mat_col(lp, i, indices, doubles);
 
   748       for (int i=1; i<=length; ++i) {
 
   749 	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
 
   755     virtual void _eraseCol(int i) {
 
   758       lpx_del_cols(lp, 1, cols);
 
   760     virtual void _eraseRow(int i) {
 
   763       lpx_del_rows(lp, 1, rows);
 
   765     void _setCoeff(int col, int row, double value) {
 
   766       /// FIXME not yet implemented
 
   768     double _getCoeff(int col, int row) {
 
   769       /// FIXME not yet implemented
 
   772     virtual void _setColLowerBound(int i, double lo) {
 
   776       int b=lpx_get_col_type(lp, i);
 
   777       double up=lpx_get_col_ub(lp, i);	
 
   782 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
 
   788 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
 
   797 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
 
   803 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
 
   805 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
 
   812     virtual double _getColLowerBound(int i) {
 
   813       int b=lpx_get_col_type(lp, i);
 
   818 	return lpx_get_col_lb(lp, i);
 
   823 	return lpx_get_col_lb(lp, i);
 
   829     virtual void _setColUpperBound(int i, double up) {
 
   833       int b=lpx_get_col_type(lp, i);
 
   834       double lo=lpx_get_col_lb(lp, i);
 
   841 	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
 
   845 	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
 
   853 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
 
   857 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
 
   859 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
 
   862 	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
 
   867 	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
 
   869 	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
 
   876     virtual double _getColUpperBound(int i) {
 
   877       int b=lpx_get_col_type(lp, i);
 
   885 	return lpx_get_col_ub(lp, i);
 
   891     virtual void _setRowLowerBound(int i, double lo) {
 
   895       int b=lpx_get_row_type(lp, i);
 
   896       double up=lpx_get_row_ub(lp, i);	
 
   901 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
 
   907 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
 
   916 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
 
   922 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
 
   924 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
 
   931     virtual double _getRowLowerBound(int i) {
 
   932       int b=lpx_get_row_type(lp, i);
 
   937 	return lpx_get_row_lb(lp, i);
 
   942 	return lpx_get_row_lb(lp, i);
 
   948     virtual void _setRowUpperBound(int i, double up) {
 
   952       int b=lpx_get_row_type(lp, i);
 
   953       double lo=lpx_get_row_lb(lp, i);
 
   960 	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
 
   964 	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
 
   972 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
 
   976 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
 
   978 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
 
   981 	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
 
   986 	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
 
   988 	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
 
   995     virtual double _getRowUpperBound(int i) {
 
   996       int b=lpx_get_row_type(lp, i);
 
  1004 	return lpx_get_row_ub(lp, i);
 
  1011     virtual double _getObjCoeff(int i) { 
 
  1012       return lpx_get_obj_coef(lp, i);
 
  1015     virtual void _setObjCoeff(int i, double obj_coef) { 
 
  1016       lpx_set_obj_coef(lp, i, obj_coef);
 
  1020     void solveSimplex() { lpx_simplex(lp); }
 
  1022     void solvePrimalSimplex() { lpx_simplex(lp); }
 
  1024     void solveDualSimplex() { lpx_simplex(lp); }
 
  1026     virtual double _getPrimal(int i) {
 
  1027       return lpx_get_col_prim(lp, i);
 
  1031     double getObjVal() { return lpx_get_obj_val(lp); }
 
  1033     int rowNum() const { return lpx_get_num_rows(lp); }
 
  1035     int colNum() const { return lpx_get_num_cols(lp); }
 
  1037     int warmUp() { return lpx_warm_up(lp); }
 
  1039     void printWarmUpStatus(int i) {
 
  1041       case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
 
  1042       case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
 
  1043       case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
 
  1044       case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
 
  1048     int getPrimalStatus() { return lpx_get_prim_stat(lp); }
 
  1050     void printPrimalStatus(int i) {
 
  1052       case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
 
  1053       case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
 
  1054       case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
 
  1055       case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
 
  1059     int getDualStatus() { return lpx_get_dual_stat(lp); }
 
  1061     void printDualStatus(int i) {
 
  1063       case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
 
  1064       case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
 
  1065       case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
 
  1066       case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
 
  1069     /// Returns the status of the slack variable assigned to row \c row.
 
  1070     int getRowStat(const Row& row) { 
 
  1071       return lpx_get_row_stat(lp, row_iter_map[row]); 
 
  1074     void printRowStatus(int i) {
 
  1076       case LPX_BS: cout << "LPX_BS" << endl; break;
 
  1077       case LPX_NL: cout << "LPX_NL" << endl; break;	
 
  1078       case LPX_NU: cout << "LPX_NU" << endl; break;
 
  1079       case LPX_NF: cout << "LPX_NF" << endl; break;
 
  1080       case LPX_NS: cout << "LPX_NS" << endl; break;
 
  1083     /// Returns the status of the variable assigned to column \c col.
 
  1084     int getColStat(const Col& col) { 
 
  1085       return lpx_get_col_stat(lp, col_iter_map[col]); 
 
  1088     void printColStatus(int i) {
 
  1090       case LPX_BS: cout << "LPX_BS" << endl; break;
 
  1091       case LPX_NL: cout << "LPX_NL" << endl; break;	
 
  1092       case LPX_NU: cout << "LPX_NU" << endl; break;
 
  1093       case LPX_NF: cout << "LPX_NF" << endl; break;
 
  1094       case LPX_NS: cout << "LPX_NS" << endl; break;
 
  1100     void solveBandB() { lpx_integer(lp); }
 
  1102     void setLP() { lpx_set_class(lp, LPX_LP); }
 
  1104     void setMIP() { lpx_set_class(lp, LPX_MIP); }
 
  1107     void _setColCont(int i) { lpx_set_col_kind(lp, i, LPX_CV); }
 
  1109     void _setColInt(int i) { lpx_set_col_kind(lp, i, LPX_IV); }
 
  1111     double _getMIPPrimal(int i) { return lpx_mip_col_val(lp, i); }
 
  1118 #endif //LEMON_LP_SOLVER_BASE_H