marci@1031: // -*- c++ -*-
marci@1152: #ifndef LEMON_LP_SOLVER_BASE_H
marci@1152: #define LEMON_LP_SOLVER_BASE_H
marci@1031: 
marci@1031: ///\ingroup misc
marci@1031: ///\file
marci@1031: 
marci@1031: // #include <stdio.h>
marci@1031: #include <stdlib.h>
marci@1097: #include <iostream>
marci@1097: #include <map>
marci@1104: #include <limits>
marci@1031: // #include <stdio>
marci@1031: //#include <stdlib>
marci@1031: 
marci@1031: #include <iostream>
marci@1031: #include <vector>
marci@1031: #include <string>
marci@1031: #include <list>
marci@1031: #include <memory>
marci@1031: #include <utility>
marci@1031: 
marci@1031: #include <lemon/invalid.h>
marci@1099: #include <expression.h>
marci@1031: //#include <stp.h>
marci@1031: //#include <lemon/max_flow.h>
marci@1031: //#include <augmenting_flow.h>
marci@1031: //#include <iter_map.h>
marci@1031: 
marci@1031: using std::cout;
marci@1031: using std::cin;
marci@1031: using std::endl;
marci@1031: 
marci@1031: namespace lemon {
marci@1031:   
marci@1031:   /// \addtogroup misc
marci@1031:   /// @{
marci@1031: 
marci@1031:   /// \brief A partitioned vector with iterable classes.
marci@1031:   ///
marci@1031:   /// This class implements a container in which the data is stored in an 
marci@1031:   /// stl vector, the range is partitioned into sets and each set is 
marci@1031:   /// doubly linked in a list. 
marci@1031:   /// That is, each class is iterable by lemon iterators, and any member of 
marci@1031:   /// the vector can bo moved to an other class.
marci@1031:   template <typename T>
marci@1031:   class IterablePartition {
marci@1031:   protected:
marci@1031:     struct Node {
marci@1031:       T data;
marci@1031:       int prev; //invalid az -1
marci@1031:       int next; 
marci@1031:     };
marci@1031:     std::vector<Node> nodes;
marci@1031:     struct Tip {
marci@1031:       int first;
marci@1031:       int last;
marci@1031:     };
marci@1031:     std::vector<Tip> tips;
marci@1031:   public:
marci@1031:     /// The classes are indexed by integers from \c 0 to \c classNum()-1.
marci@1031:     int classNum() const { return tips.size(); }
marci@1031:     /// This lemon style iterator iterates through a class. 
marci@1152:     class Class;
marci@1031:     /// Constructor. The number of classes is to be given which is fixed 
marci@1031:     /// over the life of the container. 
marci@1031:     /// The partition classes are indexed from 0 to class_num-1. 
marci@1031:     IterablePartition(int class_num) { 
marci@1031:       for (int i=0; i<class_num; ++i) {
marci@1031: 	Tip t;
marci@1031: 	t.first=t.last=-1;
marci@1031: 	tips.push_back(t);
marci@1031:       }
marci@1031:     }
marci@1031:   protected:
marci@1152:     void befuz(Class it, int class_id) {
marci@1031:       if (tips[class_id].first==-1) {
marci@1031: 	if (tips[class_id].last==-1) {
marci@1031: 	  nodes[it.i].prev=nodes[it.i].next=-1;
marci@1031: 	  tips[class_id].first=tips[class_id].last=it.i;
marci@1031: 	}
marci@1031:       } else {
marci@1031: 	nodes[it.i].prev=tips[class_id].last;
marci@1031: 	nodes[it.i].next=-1;
marci@1031: 	nodes[tips[class_id].last].next=it.i;
marci@1031: 	tips[class_id].last=it.i;
marci@1031:       }
marci@1031:     }
marci@1152:     void kifuz(Class it, int class_id) {
marci@1031:       if (tips[class_id].first==it.i) {
marci@1031: 	if (tips[class_id].last==it.i) {
marci@1031: 	  tips[class_id].first=tips[class_id].last=-1;
marci@1031: 	} else {
marci@1031: 	  tips[class_id].first=nodes[it.i].next;
marci@1031: 	  nodes[nodes[it.i].next].prev=-1;
marci@1031: 	}
marci@1031:       } else {
marci@1031: 	if (tips[class_id].last==it.i) {
marci@1031: 	  tips[class_id].last=nodes[it.i].prev;
marci@1031: 	  nodes[nodes[it.i].prev].next=-1;
marci@1031: 	} else {
marci@1031: 	  nodes[nodes[it.i].next].prev=nodes[it.i].prev;
marci@1031: 	  nodes[nodes[it.i].prev].next=nodes[it.i].next;
marci@1031: 	}
marci@1031:       }
marci@1031:     }
marci@1031:   public:
marci@1031:     /// A new element with data \c t is pushed into the vector and into class 
marci@1031:     /// \c class_id.
marci@1152:     Class push_back(const T& t, int class_id) { 
marci@1031:       Node n;
marci@1031:       n.data=t;
marci@1031:       nodes.push_back(n);
marci@1031:       int i=nodes.size()-1;
marci@1031:       befuz(i, class_id);
marci@1031:       return i;
marci@1031:     }
marci@1031:     /// A member is moved to an other class.
marci@1152:     void set(Class it, int old_class_id, int new_class_id) {
marci@1031:       kifuz(it.i, old_class_id);
marci@1031:       befuz(it.i, new_class_id);
marci@1031:     }
marci@1031:     /// Returns the data pointed by \c it.
marci@1152:     T& operator[](Class it) { return nodes[it.i].data; }
marci@1031:     /// Returns the data pointed by \c it.
marci@1152:     const T& operator[](Class it) const { return nodes[it.i].data; }
marci@1031:     ///.
marci@1152:     class Class {
marci@1031:       friend class IterablePartition;
marci@1031:     protected:
marci@1031:       int i;
marci@1031:     public:
marci@1031:       /// Default constructor.
marci@1152:       Class() { }
marci@1031:       /// This constructor constructs an iterator which points
marci@1031:       /// to the member of th container indexed by the integer _i.
marci@1152:       Class(const int& _i) : i(_i) { }
marci@1031:       /// Invalid constructor.
marci@1152:       Class(const Invalid&) : i(-1) { }
marci@1152:       friend bool operator<(const Class& x, const Class& y);
marci@1099:       friend std::ostream& operator<<(std::ostream& os, 
marci@1152: 				      const Class& it);
marci@1152:       bool operator==(const Class& node) const {return i == node.i;}
marci@1152:       bool operator!=(const Class& node) const {return i != node.i;}
marci@1031:     };
marci@1152:     friend bool operator<(const Class& x, const Class& y) {
marci@1099:       return (x.i < y.i);
marci@1099:     }
marci@1099:     friend std::ostream& operator<<(std::ostream& os, 
marci@1152: 				    const Class& it) {
marci@1099:       os << it.i;
marci@1099:       return os;
marci@1099:     }
marci@1031:     /// First member of class \c class_id.
marci@1152:     Class& first(Class& it, int class_id) const {
marci@1031:       it.i=tips[class_id].first;
marci@1031:       return it;
marci@1031:     }
marci@1031:     /// Next member.
marci@1152:     Class& next(Class& it) const {
marci@1031:       it.i=nodes[it.i].next;
marci@1031:       return it;
marci@1031:     }
marci@1031:     /// True iff the iterator is valid.
marci@1152:     bool valid(const Class& it) const { return it.i!=-1; }
marci@1152: 
marci@1152:     class ClassIt : public Class {
marci@1152:       const IterablePartition* iterable_partition;
marci@1152:     public:
marci@1152:       ClassIt() { }
marci@1152:       ClassIt(Invalid i) : Class(i) { }
marci@1152:       ClassIt(const IterablePartition& _iterable_partition, 
marci@1152: 	      const int& i) : iterable_partition(&_iterable_partition) {
marci@1152:         _iterable_partition.first(*this, i);
marci@1152:       }
marci@1152:       ClassIt(const IterablePartition& _iterable_partition, 
marci@1152: 	      const Class& _class) : 
marci@1152: 	Class(_class), iterable_partition(&_iterable_partition) { }
marci@1152:       ClassIt& operator++() {
marci@1152:         iterable_partition->next(*this);
marci@1152:         return *this;
marci@1152:       }
marci@1152:     };
marci@1152: 
marci@1031:   };
marci@1031: 
marci@1097: 
marci@1031:   /*! \e
marci@1143:     \todo kellenene uj iterable structure bele, mert ez nem az igazi
marci@1111:     \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
marci@1111:     \todo LEKERDEZESEK!!!
marci@1111:     \todo DOKSI!!!! Doxygen group!!!
marci@1111:     The aim of this class is to give a general surface to different 
marci@1111:     solvers, i.e. it makes possible to write algorithms using LP's, 
marci@1111:     in which the solver can be changed to an other one easily.
marci@1112:     \nosubgrouping
marci@1111:   */
marci@1048:   template <typename _Value>
athos@1241:   class LpSolverBase {
marci@1112:     
marci@1113:     /*! @name Uncategorized functions and types (public members)
marci@1112:     */
marci@1112:     //@{
marci@1031:   public:
marci@1112: 
marci@1112:     //UNCATEGORIZED
marci@1112: 
marci@1031:     /// \e
marci@1152:     typedef IterablePartition<int> Rows;
marci@1152:     /// \e
marci@1152:     typedef IterablePartition<int> Cols;
marci@1152:     /// \e
marci@1048:     typedef _Value Value;
marci@1048:     /// \e
marci@1152:     typedef Rows::Class Row;
marci@1031:     /// \e
marci@1152:     typedef Cols::Class Col;
marci@1074:   public:
marci@1031:     /// \e
marci@1031:     IterablePartition<int> row_iter_map;
marci@1031:     /// \e
marci@1031:     IterablePartition<int> col_iter_map;
marci@1031:     /// \e
marci@1144:     std::vector<Row> int_row_map;
marci@1143:     /// \e
marci@1144:     std::vector<Col> int_col_map;
marci@1143:     /// \e
marci@1074:     const int VALID_CLASS;
marci@1031:     /// \e
marci@1074:     const int INVALID_CLASS;
marci@1104:     /// \e 
athos@1241:     static const Value INF;
marci@1031:   public:
marci@1031:     /// \e
athos@1241:     LpSolverBase() : row_iter_map(2), 
marci@1031: 		     col_iter_map(2), 
marci@1074: 		     VALID_CLASS(0), INVALID_CLASS(1) { }
marci@1031:     /// \e
athos@1241:     virtual ~LpSolverBase() { }
marci@1112:     //@}
marci@1081: 
marci@1112:     /*! @name Medium level interface (public members)
marci@1112:       These functions appear in the low level and also in the high level 
marci@1112:       interfaces thus these each of these functions have to be implemented 
marci@1112:       only once in the different interfaces.
marci@1112:       This means that these functions have to be reimplemented for all of the 
marci@1112:       different lp solvers. These are basic functions, and have the same 
marci@1112:       parameter lists in the low and high level interfaces. 
marci@1112:     */
marci@1112:     //@{
marci@1112:   public:
marci@1081: 
marci@1112:     //UNCATEGORIZED FUNCTIONS
marci@1112: 
marci@1031:     /// \e
marci@1031:     virtual void setMinimize() = 0;
marci@1031:     /// \e
marci@1031:     virtual void setMaximize() = 0;
marci@1081: 
marci@1112:     //SOLVER FUNCTIONS
marci@1081: 
marci@1112:     /// \e
marci@1112:     virtual void solveSimplex() = 0;
marci@1112:     /// \e
marci@1112:     virtual void solvePrimalSimplex() = 0;
marci@1112:     /// \e
marci@1112:     virtual void solveDualSimplex() = 0;
marci@1112: 
marci@1112:     //SOLUTION RETRIEVING
marci@1112: 
marci@1112:     /// \e
athos@1241:     virtual Value getObjVal() = 0;
marci@1112: 
marci@1112:     //OTHER FUNCTIONS
marci@1112: 
marci@1112:     /// \e
marci@1112:     virtual int rowNum() const = 0;
marci@1112:     /// \e
marci@1112:     virtual int colNum() const = 0;
marci@1112:     /// \e
marci@1112:     virtual int warmUp() = 0;
marci@1112:     /// \e
marci@1112:     virtual void printWarmUpStatus(int i) = 0;
marci@1112:     /// \e
marci@1112:     virtual int getPrimalStatus() = 0;
marci@1112:     /// \e
marci@1112:     virtual void printPrimalStatus(int i) = 0;
marci@1112:     /// \e
marci@1112:     virtual int getDualStatus() = 0;
marci@1112:     /// \e
marci@1112:     virtual void printDualStatus(int i) = 0;
marci@1144:     /// Returns the status of the slack variable assigned to row \c row.
marci@1144:     virtual int getRowStat(const Row& row) = 0;
marci@1112:     /// \e
marci@1112:     virtual void printRowStatus(int i) = 0;
marci@1144:     /// Returns the status of the variable assigned to column \c col.
marci@1144:     virtual int getColStat(const Col& col) = 0;
marci@1112:     /// \e
marci@1112:     virtual void printColStatus(int i) = 0;
marci@1112: 
marci@1112:     //@}
marci@1112: 
marci@1112:     /*! @name Low level interface (protected members)
marci@1112:       Problem manipulating functions in the low level interface
marci@1112:     */
marci@1112:     //@{
marci@1074:   protected:
marci@1112: 
marci@1112:     //MATRIX MANIPULATING FUNCTIONS
marci@1112: 
marci@1031:     /// \e
marci@1111:     virtual int _addCol() = 0;
marci@1111:     /// \e
marci@1074:     virtual int _addRow() = 0;
marci@1031:     /// \e
marci@1111:     virtual void _eraseCol(int i) = 0;
marci@1111:     /// \e
marci@1111:     virtual void _eraseRow(int i) = 0;
marci@1081:     /// \e
marci@1081:     virtual void _setRowCoeffs(int i, 
athos@1241: 			       const std::vector<std::pair<int, Value> >& coeffs) = 0;
marci@1081:     /// \e
marci@1143:     /// This routine modifies \c coeffs only by the \c push_back method.
marci@1143:     virtual void _getRowCoeffs(int i, 
athos@1241: 			       std::vector<std::pair<int, Value> >& coeffs) = 0;
marci@1152:     /// \e
marci@1081:     virtual void _setColCoeffs(int i, 
athos@1241: 			       const std::vector<std::pair<int, Value> >& coeffs) = 0;
marci@1143:     /// \e
marci@1143:     /// This routine modifies \c coeffs only by the \c push_back method.
marci@1143:     virtual void _getColCoeffs(int i, 
athos@1241: 			       std::vector<std::pair<int, Value> >& coeffs) = 0;
marci@1081:     /// \e
athos@1241:     virtual void _setCoeff(int col, int row, Value value) = 0;
marci@1152:     /// \e
athos@1241:     virtual Value _getCoeff(int col, int row) = 0;
marci@1152:     //  public:
marci@1152:     //    /// \e
marci@1152:     //    enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
marci@1081:   protected:
marci@1081:     /// \e
marci@1110:     /// The lower bound of a variable (column) have to be given by an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or -INF.
athos@1241:     virtual void _setColLowerBound(int i, Value value) = 0;
marci@1110:     /// \e
marci@1111:     /// The lower bound of a variable (column) is an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or -INF.
athos@1241:     virtual Value _getColLowerBound(int i) = 0;
marci@1111:     /// \e
marci@1110:     /// The upper bound of a variable (column) have to be given by an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or INF.
athos@1241:     virtual void _setColUpperBound(int i, Value value) = 0;
marci@1110:     /// \e
marci@1110:     /// The upper bound of a variable (column) is an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or INF.
athos@1241:     virtual Value _getColUpperBound(int i) = 0;
marci@1110:     /// \e
marci@1111:     /// The lower bound of a linear expression (row) have to be given by an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or -INF.
athos@1241:     virtual void _setRowLowerBound(int i, Value value) = 0;
marci@1081:     /// \e
marci@1111:     /// The lower bound of a linear expression (row) is an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or -INF.
athos@1241:     virtual Value _getRowLowerBound(int i) = 0;
marci@1111:     /// \e
marci@1111:     /// The upper bound of a linear expression (row) have to be given by an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or INF.
athos@1241:     virtual void _setRowUpperBound(int i, Value value) = 0;
marci@1111:     /// \e
marci@1111:     /// The upper bound of a linear expression (row) is an 
athos@1241:     /// extended number of type Value, i.e. a finite number of type 
athos@1241:     /// Value or INF.
athos@1241:     virtual Value _getRowUpperBound(int i) = 0;
marci@1081:     /// \e
athos@1241:     virtual void _setObjCoeff(int i, Value obj_coef) = 0;
marci@1081:     /// \e
athos@1241:     virtual Value _getObjCoeff(int i) = 0;
marci@1112:     
marci@1112:     //SOLUTION RETRIEVING
marci@1081: 
marci@1111:     /// \e
athos@1241:     virtual Value _getPrimal(int i) = 0;
marci@1112:     //@}
marci@1112:     
marci@1112:     /*! @name High level interface (public members)
marci@1112:       Problem manipulating functions in the high level interface
marci@1112:     */
marci@1112:     //@{
marci@1112:   public:
marci@1081: 
marci@1112:     //MATRIX MANIPULATING FUNCTIONS
marci@1081: 
marci@1074:     /// \e
marci@1144:     Col addCol() {
marci@1074:       int i=_addCol();  
marci@1144:       Col col;
marci@1144:       col_iter_map.first(col, INVALID_CLASS);
marci@1144:       if (col_iter_map.valid(col)) { //van hasznalhato hely
marci@1144: 	col_iter_map.set(col, INVALID_CLASS, VALID_CLASS);
marci@1144: 	col_iter_map[col]=i;
marci@1074:       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@1144: 	col=col_iter_map.push_back(i, VALID_CLASS);
marci@1074:       }
marci@1144:       int_col_map.push_back(col);
marci@1144:       return col;
marci@1074:     }
marci@1074:     /// \e
marci@1144:     Row addRow() {
marci@1111:       int i=_addRow();
marci@1144:       Row row;
marci@1144:       row_iter_map.first(row, INVALID_CLASS);
marci@1144:       if (row_iter_map.valid(row)) { //van hasznalhato hely
marci@1144: 	row_iter_map.set(row, INVALID_CLASS, VALID_CLASS);
marci@1144: 	row_iter_map[row]=i;
marci@1111:       } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@1144: 	row=row_iter_map.push_back(i, VALID_CLASS);
marci@1031:       }
marci@1144:       int_row_map.push_back(row);
marci@1144:       return row;
marci@1074:     }
marci@1074:     /// \e
marci@1144:     void eraseCol(const Col& col) {
marci@1144:       col_iter_map.set(col, VALID_CLASS, INVALID_CLASS);
marci@1074:       int cols[2];
marci@1144:       cols[1]=col_iter_map[col];
marci@1074:       _eraseCol(cols[1]);
marci@1144:       col_iter_map[col]=0; //glpk specifikus, de kell ez??
marci@1144:       Col it;
marci@1074:       for (col_iter_map.first(it, VALID_CLASS); 
marci@1074: 	   col_iter_map.valid(it); col_iter_map.next(it)) {
marci@1074: 	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
marci@1074:       }
marci@1143:       int_col_map.erase(int_col_map.begin()+cols[1]);
marci@1031:     }
marci@1031:     /// \e
marci@1144:     void eraseRow(const Row& row) {
marci@1144:       row_iter_map.set(row, VALID_CLASS, INVALID_CLASS);
marci@1074:       int rows[2];
marci@1144:       rows[1]=row_iter_map[row];
marci@1074:       _eraseRow(rows[1]);
marci@1144:       row_iter_map[row]=0; //glpk specifikus, de kell ez??
marci@1144:       Row it;
marci@1074:       for (row_iter_map.first(it, VALID_CLASS); 
marci@1074: 	   row_iter_map.valid(it); row_iter_map.next(it)) {
marci@1074: 	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
marci@1074:       }
marci@1143:       int_row_map.erase(int_row_map.begin()+rows[1]);
marci@1074:     }
marci@1031:     /// \e
athos@1241:     void setCoeff(Col col, Row row, Value value) {
marci@1152:       _setCoeff(col_iter_map[col], row_iter_map[row], value);
marci@1152:     }
marci@1152:     /// \e
athos@1241:     Value getCoeff(Col col, Row row) {
marci@1152:       return _getCoeff(col_iter_map[col], row_iter_map[row], value);
marci@1152:     }
marci@1152:     /// \e
athos@1241:     void setColLowerBound(Col col, Value lo) {
marci@1144:       _setColLowerBound(col_iter_map[col], lo);
marci@1111:     }
marci@1111:     /// \e
athos@1241:     Value getColLowerBound(Col col) {
marci@1144:       return _getColLowerBound(col_iter_map[col]);
marci@1111:     }
marci@1111:     /// \e
athos@1241:     void setColUpperBound(Col col, Value up) {
marci@1144:       _setColUpperBound(col_iter_map[col], up);
marci@1110:     }
marci@1110:     /// \e
athos@1241:     Value getColUpperBound(Col col) {      
marci@1144:       return _getColUpperBound(col_iter_map[col]);
marci@1111:     }
marci@1111:     /// \e
athos@1241:     void setRowLowerBound(Row row, Value lo) {
marci@1144:       _setRowLowerBound(row_iter_map[row], lo);
marci@1110:     }
marci@1110:     /// \e
athos@1241:     Value getRowLowerBound(Row row) {
marci@1144:       return _getRowLowerBound(row_iter_map[row]);
marci@1110:     }
marci@1110:     /// \e
athos@1241:     void setRowUpperBound(Row row, Value up) {
marci@1144:       _setRowUpperBound(row_iter_map[row], up);
marci@1081:     }
marci@1031:     /// \e
athos@1241:     Value getRowUpperBound(Row row) {      
marci@1144:       return _getRowUpperBound(row_iter_map[row]);
marci@1111:     }
marci@1111:     /// \e
athos@1241:     void setObjCoeff(const Col& col, Value obj_coef) {
marci@1152:       _setObjCoeff(col_iter_map[col], obj_coef);
marci@1111:     }
marci@1111:     /// \e
athos@1241:     Value getObjCoeff(const Col& col) {
marci@1152:       return _getObjCoeff(col_iter_map[col]);
marci@1081:     }
marci@1081: 
marci@1112:     //SOLUTION RETRIEVING FUNCTIONS
marci@1112: 
marci@1112:     /// \e
athos@1241:     Value getPrimal(const Col& col) {
marci@1144:       return _getPrimal(col_iter_map[col]);
marci@1112:     }    
marci@1112: 
marci@1112:     //@}
marci@1112: 
marci@1112:     /*! @name User friend interface
marci@1112:       Problem manipulating functions in the user friend interface
marci@1112:     */
marci@1112:     //@{
marci@1112: 
marci@1112:     //EXPRESSION TYPES
marci@1099: 
marci@1099:     /// \e
athos@1241:     typedef Expr<Col, Value> Expression;
marci@1099:     /// \e
athos@1241:     typedef Expr<Row, Value> DualExpression;
marci@1144:     /// \e
athos@1241:     typedef Constr<Col, Value> Constraint;
marci@1112: 
marci@1112:     //MATRIX MANIPULATING FUNCTIONS
marci@1112: 
marci@1099:     /// \e
marci@1144:     void setRowCoeffs(Row row, const Expression& expr) {
athos@1241:       std::vector<std::pair<int, Value> > row_coeffs;
marci@1099:       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
marci@1099: 	  i!=expr.data.end(); ++i) {
marci@1099: 	row_coeffs.push_back(std::make_pair
marci@1099: 			     (col_iter_map[(*i).first], (*i).second));
marci@1099:       }
marci@1144:       _setRowCoeffs(row_iter_map[row], row_coeffs);
marci@1144:     }
marci@1144:     /// \e 
marci@1144:     void setRow(Row row, const Constraint& constr) {
marci@1144:       setRowCoeffs(row, constr.expr);
marci@1144:       setRowLowerBound(row, constr.lo);
marci@1144:       setRowUpperBound(row, constr.up);
marci@1144:     }
marci@1144:     /// \e 
marci@1144:     Row addRow(const Constraint& constr) {
marci@1144:       Row row=addRow();
marci@1144:       setRowCoeffs(row, constr.expr);
marci@1144:       setRowLowerBound(row, constr.lo);
marci@1144:       setRowUpperBound(row, constr.up);
marci@1144:       return row;
marci@1099:     }
marci@1099:     /// \e
marci@1143:     /// This routine modifies \c expr by only adding to it.
marci@1144:     void getRowCoeffs(Row row, Expression& expr) {
athos@1241:       std::vector<std::pair<int, Value> > row_coeffs;
marci@1144:       _getRowCoeffs(row_iter_map[row], row_coeffs);
athos@1241:       for(typename std::vector<std::pair<int, Value> >::const_iterator 
marci@1143:  	    i=row_coeffs.begin(); i!=row_coeffs.end(); ++i) {
marci@1143:  	expr+= (*i).second*int_col_map[(*i).first];
marci@1143:       }
marci@1143:     }
marci@1143:     /// \e
marci@1144:     void setColCoeffs(Col col, const DualExpression& expr) {
athos@1241:       std::vector<std::pair<int, Value> > col_coeffs;
marci@1099:       for(typename DualExpression::Data::const_iterator i=expr.data.begin(); 
marci@1099: 	  i!=expr.data.end(); ++i) {
marci@1099: 	col_coeffs.push_back(std::make_pair
marci@1099: 			     (row_iter_map[(*i).first], (*i).second));
marci@1099:       }
marci@1144:       _setColCoeffs(col_iter_map[col], col_coeffs);
marci@1099:     }
marci@1099:     /// \e
marci@1143:     /// This routine modifies \c expr by only adding to it.
marci@1144:     void getColCoeffs(Col col, DualExpression& expr) {
athos@1241:       std::vector<std::pair<int, Value> > col_coeffs;
marci@1144:       _getColCoeffs(col_iter_map[col], col_coeffs);
athos@1241:       for(typename std::vector<std::pair<int, Value> >::const_iterator 
marci@1143:  	    i=col_coeffs.begin(); i!=col_coeffs.end(); ++i) {
marci@1143:  	expr+= (*i).second*int_row_map[(*i).first];
marci@1143:       }
marci@1143:     }
marci@1143:     /// \e
marci@1099:     void setObjCoeffs(const Expression& expr) {
marci@1152:       // writing zero everywhere
marci@1152:       for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
marci@1152: 	setObjCoeff(it, 0.0);
marci@1152:       // writing the data needed
marci@1099:       for(typename Expression::Data::const_iterator i=expr.data.begin(); 
marci@1099: 	  i!=expr.data.end(); ++i) {
marci@1152: 	setObjCoeff((*i).first, (*i).second);
marci@1099:       }
marci@1099:     }
marci@1143:     /// \e
marci@1143:     /// This routine modifies \c expr by only adding to it.
marci@1143:     void getObjCoeffs(Expression& expr) {
marci@1152:       for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
marci@1152: 	expr+=getObjCoeff(it)*it;
marci@1152:     }
marci@1152:     //@}
marci@1152: 
marci@1152: 
marci@1152:     /*! @name MIP functions and types (public members)
marci@1152:     */
marci@1152:     //@{
marci@1152:   public:
marci@1152:     /// \e
marci@1152:     virtual void solveBandB() = 0;
marci@1152:     /// \e
marci@1152:     virtual void setLP() = 0;
marci@1152:     /// \e
marci@1152:     virtual void setMIP() = 0;
marci@1152:   protected:
marci@1152:    /// \e
marci@1152:     virtual void _setColCont(int i) = 0;
marci@1152:     /// \e
marci@1152:     virtual void _setColInt(int i) = 0;
marci@1153:     /// \e
athos@1241:     virtual Value _getMIPPrimal(int i) = 0;
marci@1152:   public:
marci@1152:     /// \e
marci@1152:     void setColCont(Col col) {
marci@1152:       _setColCont(col_iter_map[col]);
marci@1152:     }
marci@1152:     /// \e
marci@1152:     void setColInt(Col col) {
marci@1152:       _setColInt(col_iter_map[col]);
marci@1143:     }
marci@1153:     /// \e
athos@1241:     Value getMIPPrimal(Col col) {
marci@1153:       return _getMIPPrimal(col_iter_map[col]);
marci@1153:     }
marci@1112:     //@}
marci@1031:   };
marci@1031: 
marci@1031: } //namespace lemon
marci@1031: 
marci@1152: #endif //LEMON_LP_SOLVER_BASE_H