# HG changeset patch # User deba # Date 1171566914 0 # Node ID 3a5e67bd42d2deeb4e50439acb4dec595c2b78fe # Parent 2aabce55857427e3a2f08fb00e302b6cf244b0da Lp row and col getter function lp section reader and writer for lemon IO diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_base.h --- a/lemon/lp_base.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_base.h Thu Feb 15 19:15:14 2007 +0000 @@ -49,7 +49,7 @@ _lp_bits::LpId cols; public: - + ///Possible outcomes of an LP solving procedure enum SolveExitStatus { ///This means that the problem has been successfully solved: either @@ -122,6 +122,7 @@ int id; friend class LpSolverBase; friend class MipSolverBase; + explicit Col(int _id) : id(_id) {} public: typedef Value ExprValue; typedef True LpSolverCol; @@ -165,6 +166,7 @@ protected: int id; friend class LpSolverBase; + explicit Row(int _id) : id(_id) {} public: typedef Value ExprValue; typedef True LpSolverRow; @@ -177,6 +179,22 @@ bool operator!=(Row c) const {return id!=c.id;} }; + class RowIt : public Row { + LpSolverBase *_lp; + public: + RowIt() {} + RowIt(LpSolverBase &lp) : _lp(&lp) + { + _lp->rows.firstFix(id); + } + RowIt(const Invalid&) : Row(INVALID) {} + RowIt &operator++() + { + _lp->rows.nextFix(id); + return *this; + } + }; + static int id(const Row& row) { return row.id; } protected: @@ -189,6 +207,14 @@ return rows.floatingId(id(row)); } + Col _item(int id, Col) const { + return Col(cols.fixId(id)); + } + + Row _item(int id, Row) const { + return Row(rows.fixId(id)); + } + public: @@ -581,11 +607,60 @@ private: - template - class MappedIterator { + template + class MappedOutputIterator { public: - typedef _Base Base; + typedef std::insert_iterator<_Expr> Base; + + typedef std::output_iterator_tag iterator_category; + typedef void difference_type; + typedef void value_type; + typedef void reference; + typedef void pointer; + + MappedOutputIterator(const Base& _base, const LpSolverBase& _lp) + : base(_base), lp(_lp) {} + + MappedOutputIterator& operator*() { + return *this; + } + + MappedOutputIterator& operator=(const std::pair& value) { + *base = std::make_pair(lp._item(value.first, typename _Expr::Key()), + value.second); + return *this; + } + + MappedOutputIterator& operator++() { + ++base; + return *this; + } + + MappedOutputIterator operator++(int) { + MappedOutputIterator tmp(*this); + ++base; + return tmp; + } + + bool operator==(const MappedOutputIterator& it) const { + return base == it.base; + } + + bool operator!=(const MappedOutputIterator& it) const { + return base != it.base; + } + + private: + Base base; + const LpSolverBase& lp; + }; + + template + class MappedInputIterator { + public: + + typedef typename Expr::const_iterator Base; typedef typename Base::iterator_category iterator_category; typedef typename Base::difference_type difference_type; @@ -599,7 +674,7 @@ value_type value; }; - MappedIterator(const Base& _base, const LpSolverBase& _lp) + MappedInputIterator(const Base& _base, const LpSolverBase& _lp) : base(_base), lp(_lp) {} reference operator*() { @@ -610,22 +685,22 @@ return pointer(operator*()); } - MappedIterator& operator++() { + MappedInputIterator& operator++() { ++base; return *this; } - MappedIterator& operator++(int) { - MappedIterator tmp(*this); + MappedInputIterator operator++(int) { + MappedInputIterator tmp(*this); ++base; return tmp; } - bool operator==(const MappedIterator& it) const { + bool operator==(const MappedInputIterator& it) const { return base == it.base; } - bool operator!=(const MappedIterator& it) const { + bool operator!=(const MappedInputIterator& it) const { return base != it.base; } @@ -637,9 +712,14 @@ protected: /// STL compatible iterator for lp col - typedef MappedIterator LpRowIterator; + typedef MappedInputIterator ConstRowIterator; /// STL compatible iterator for lp row - typedef MappedIterator LpColIterator; + typedef MappedInputIterator ConstColIterator; + + /// STL compatible iterator for lp col + typedef MappedOutputIterator RowIterator; + /// STL compatible iterator for lp row + typedef MappedOutputIterator ColIterator; //Abstract virtual functions virtual LpSolverBase &_newLp() = 0; @@ -659,11 +739,14 @@ virtual void _eraseRow(int row) = 0; virtual void _getColName(int col, std::string & name) = 0; virtual void _setColName(int col, const std::string & name) = 0; - virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e) = 0; - virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e) = 0; + virtual void _setRowCoeffs(int i, ConstRowIterator b, + ConstRowIterator e) = 0; + virtual void _getRowCoeffs(int i, RowIterator b) = 0; + virtual void _setColCoeffs(int i, ConstColIterator b, + ConstColIterator e) = 0; + virtual void _getColCoeffs(int i, ColIterator b) = 0; virtual void _setCoeff(int row, int col, Value value) = 0; virtual Value _getCoeff(int row, int col) = 0; - virtual void _setColLowerBound(int i, Value value) = 0; virtual Value _getColLowerBound(int i) = 0; virtual void _setColUpperBound(int i, Value value) = 0; @@ -786,8 +869,18 @@ ///a better one. void col(Col c,const DualExpr &e) { e.simplify(); - _setColCoeffs(_lpId(c), LpColIterator(e.begin(), *this), - LpColIterator(e.end(), *this)); + _setColCoeffs(_lpId(c), ConstColIterator(e.begin(), *this), + ConstColIterator(e.end(), *this)); + } + + ///Get a column (i.e a dual constraint) of the LP + + ///\param r is the column to get + ///\return the dual expression associated to the column + DualExpr col(Col c) { + DualExpr e; + _getColCoeffs(_lpId(c), ColIterator(std::inserter(e, e.end()), *this)); + return e; } ///Add a new column to the LP @@ -883,9 +976,9 @@ ///added or not. void row(Row r, Value l,const Expr &e, Value u) { e.simplify(); - _setRowCoeffs(_lpId(r), LpRowIterator(e.begin(), *this), - LpRowIterator(e.end(), *this)); - _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp()); + _setRowCoeffs(_lpId(r), ConstRowIterator(e.begin(), *this), + ConstRowIterator(e.end(), *this)); + _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp()); } ///Set a row (i.e a constraint) of the LP @@ -897,6 +990,17 @@ c.expr(), c.upperBounded()?c.upperBound():INF); } + + ///Get a row (i.e a constraint) of the LP + + ///\param r is the row to get + ///\return the expression associated to the row + Expr row(Row r) { + Expr e; + _getRowCoeffs(_lpId(r), RowIterator(std::inserter(e, e.end()), *this)); + return e; + } + ///Add a new row (i.e a new constraint) to the LP ///\param l is the lower bound (-\ref INF means no bound) @@ -1177,6 +1281,21 @@ obj_const_comp=e.constComp(); } + ///Get the objective function + + ///\return the objective function as a linear expression of type \ref Expr. + Expr obj() { + Expr e; + for (ColIt it(*this); it != INVALID; ++it) { + double c = objCoeff(it); + if (c != 0.0) { + e.insert(std::make_pair(it, c)); + } + } + return e; + } + + ///Maximize void max() { _setMax(); } ///Minimize diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_cplex.cc --- a/lemon/lp_cplex.cc Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_cplex.cc Thu Feb 15 19:15:14 2007 +0000 @@ -109,13 +109,13 @@ } ///\warning Data at index 0 is ignored in the arrays. - void LpCplex::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e) + void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) { std::vector indices; std::vector rowlist; std::vector values; - for(LpRowIterator it=b; it!=e; ++it) { + for(ConstRowIterator it=b; it!=e; ++it) { indices.push_back(it->first); values.push_back(it->second); rowlist.push_back(i); @@ -124,14 +124,18 @@ status = CPXchgcoeflist(env, lp, values.size(), &rowlist[0], &indices[0], &values[0]); } + + void LpSoplex::_getRowCoeffs(int i, RowIterator b) { + /// \todo implement + } - void LpCplex::_setColCoeffs(int i, LpColIterator b, LpColIterator e) + void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) { std::vector indices; std::vector collist; std::vector values; - for(LpColIterator it=b; it!=e; ++it) { + for(ConstColIterator it=b; it!=e; ++it) { indices.push_back(it->first); values.push_back(it->second); collist.push_back(i); @@ -140,6 +144,10 @@ status = CPXchgcoeflist(env, lp, values.size(), &indices[0], &collist[0], &values[0]); } + + void LpSoplex::_getColCoeffs(int i, ColIterator b) { + /// \todo implement + } void LpCplex::_setCoeff(int row, int col, Value value) { diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_cplex.h --- a/lemon/lp_cplex.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_cplex.h Thu Feb 15 19:15:14 2007 +0000 @@ -62,8 +62,10 @@ virtual void _eraseRow(int i); virtual void _getColName(int col, std::string & name); virtual void _setColName(int col, const std::string & name); - virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e); - virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e); + virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e); + virtual void _getRowCoeffs(int i, RowIterator b); + virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e); + virtual void _getColCoeffs(int i, ColIterator b); virtual void _setCoeff(int row, int col, Value value); virtual Value _getCoeff(int row, int col); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_glpk.cc --- a/lemon/lp_glpk.cc Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_glpk.cc Thu Feb 15 19:15:14 2007 +0000 @@ -126,7 +126,7 @@ } - void LpGlpk::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e) + void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) { std::vector indices; std::vector values; @@ -134,15 +134,30 @@ indices.push_back(0); values.push_back(0); - for(LpRowIterator it=b; it!=e; ++it) { + for(ConstRowIterator it=b; it!=e; ++it) { indices.push_back(it->first); values.push_back(it->second); } lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]); } + + void LpGlpk::_getRowCoeffs(int i, RowIterator b) + { + int length = lpx_get_mat_row(lp, i, 0, 0); + + std::vector indices(length + 1); + std::vector values(length + 1); + + lpx_get_mat_row(lp, i, &indices[0], &values[0]); + + for (int i = 1; i <= length; ++i) { + *b = std::make_pair(indices[i], values[i]); + ++b; + } + } - void LpGlpk::_setColCoeffs(int i, LpColIterator b, LpColIterator e) { + void LpGlpk::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) { std::vector indices; std::vector values; @@ -150,7 +165,7 @@ indices.push_back(0); values.push_back(0); - for(LpColIterator it=b; it!=e; ++it) { + for(ConstColIterator it=b; it!=e; ++it) { indices.push_back(it->first); values.push_back(it->second); } @@ -158,6 +173,20 @@ lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]); } + void LpGlpk::_getColCoeffs(int i, ColIterator b) + { + int length = lpx_get_mat_col(lp, i, 0, 0); + + std::vector indices(length + 1); + std::vector values(length + 1); + + lpx_get_mat_col(lp, i, &indices[0], &values[0]); + + for (int i = 1; i <= length; ++i) { + *b = std::make_pair(indices[i], values[i]); + ++b; + } + } void LpGlpk::_setCoeff(int row, int col, Value value) { @@ -223,8 +252,8 @@ int length=lpx_get_mat_row(lp, row, 0, 0); - std::vector indices(length + 2); - std::vector values(length + 2); + std::vector indices(length + 1); + std::vector values(length + 1); lpx_get_mat_row(lp, row, &indices[0], &values[0]); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_glpk.h --- a/lemon/lp_glpk.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_glpk.h Thu Feb 15 19:15:14 2007 +0000 @@ -57,8 +57,10 @@ virtual void _eraseRow(int i); virtual void _getColName(int col, std::string & name); virtual void _setColName(int col, const std::string & name); - virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e); - virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e); + virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e); + virtual void _getRowCoeffs(int i, RowIterator b); + virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e); + virtual void _getColCoeffs(int i, ColIterator b); virtual void _setCoeff(int row, int col, Value value); virtual Value _getCoeff(int row, int col); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_skeleton.cc --- a/lemon/lp_skeleton.cc Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_skeleton.cc Thu Feb 15 19:15:14 2007 +0000 @@ -58,10 +58,16 @@ } - void LpSkeleton::_setRowCoeffs(int, LpRowIterator, LpRowIterator) { + void LpSkeleton::_setRowCoeffs(int, ConstRowIterator, ConstRowIterator) { + } + + void LpSkeleton::_getRowCoeffs(int, RowIterator) { } - void LpSkeleton::_setColCoeffs(int, LpColIterator, LpColIterator) { + void LpSkeleton::_setColCoeffs(int, ConstColIterator, ConstColIterator) { + } + + void LpSkeleton::_getColCoeffs(int, ColIterator) { } void LpSkeleton::_setCoeff(int, int, Value ) diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_skeleton.h --- a/lemon/lp_skeleton.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_skeleton.h Thu Feb 15 19:15:14 2007 +0000 @@ -49,9 +49,13 @@ virtual void _setColName(int col, const std::string & name); /// \e - virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e); + virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e); /// \e - virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e); + virtual void _getRowCoeffs(int i, RowIterator b); + /// \e + virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e); + /// \e + virtual void _getColCoeffs(int i, ColIterator b); /// Set one element of the coefficient matrix virtual void _setCoeff(int row, int col, Value value); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_soplex.cc --- a/lemon/lp_soplex.cc Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_soplex.cc Thu Feb 15 19:15:14 2007 +0000 @@ -99,25 +99,41 @@ } - void LpSoplex::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e) { + void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) { for (int j = 0; j < soplex->nCols(); ++j) { soplex->changeElement(i, j, 0.0); } - for(LpRowIterator it = b; it != e; ++it) { + for(ConstRowIterator it = b; it != e; ++it) { soplex->changeElement(i, it->first, it->second); } solved = false; } + + void LpSoplex::_getRowCoeffs(int i, RowIterator b) { + const soplex::SVector& vec = soplex->rowVector(i); + for (int k = 0; k < vec.size(); ++k) { + *b = std::make_pair(vec.index(k), vec.value(k)); + ++b; + } + } - void LpSoplex::_setColCoeffs(int j, LpColIterator b, LpColIterator e) { + void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) { for (int i = 0; i < soplex->nRows(); ++i) { soplex->changeElement(i, j, 0.0); } - for(LpColIterator it = b; it != e; ++it) { + for(ConstColIterator it = b; it != e; ++it) { soplex->changeElement(it->first, j, it->second); } solved = false; } + + void LpSoplex::_getColCoeffs(int i, ColIterator b) { + const soplex::SVector& vec = soplex->colVector(i); + for (int k = 0; k < vec.size(); ++k) { + *b = std::make_pair(vec.index(k), vec.value(k)); + ++b; + } + } void LpSoplex::_setCoeff(int i, int j, Value value) { soplex->changeElement(i, j, value); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_soplex.h --- a/lemon/lp_soplex.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_soplex.h Thu Feb 15 19:15:14 2007 +0000 @@ -72,8 +72,10 @@ virtual void _eraseRow(int i); virtual void _getColName(int col, std::string & name); virtual void _setColName(int col, const std::string & name); - virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e); - virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e); + virtual void _setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e); + virtual void _getRowCoeffs(int i, RowIterator b); + virtual void _setColCoeffs(int i, ConstColIterator b, ConstColIterator e); + virtual void _getColCoeffs(int i, ColIterator b); virtual void _setCoeff(int row, int col, Value value); virtual Value _getCoeff(int row, int col); virtual void _setColLowerBound(int i, Value value); diff -r 2aabce558574 -r 3a5e67bd42d2 lemon/lp_utils.h --- a/lemon/lp_utils.h Thu Feb 15 14:22:08 2007 +0000 +++ b/lemon/lp_utils.h Thu Feb 15 19:15:14 2007 +0000 @@ -68,11 +68,16 @@ private: + enum SubSection { + CONSTRAINTS, BOUNDS, OBJECTIVE + }; + enum Relation { LE, EQ, GE }; - std::istream& readConstraint(std::istream& is, LpSolverBase::Constr& c) { + std::istream& readConstraint(std::istream& is) { + LpSolverBase::Constr c; char x; LpSolverBase::Expr e1, e2; Relation op1; @@ -82,13 +87,27 @@ readRelation(is, op1); is >> std::ws; readExpression(is, e2); + is >> std::ws; if (!is.get(x)) { if (op1 == LE) { + if (e1.size() == 0) { + c = e2 >= e1; + } else { + c = e1 <= e2; + } c = e1 <= e2; } else if (op1 == GE) { - c = e1 >= e2; + if (e1.size() == 0) { + c = e2 <= e1; + } else { + c = e1 >= e2; + } } else { - c = e1 == e2; + if (e1.size() == 0) { + c = e2 == e1; + } else { + c = e1 == e2; + } } } else { is.putback(x); @@ -108,7 +127,104 @@ } else { c = e1.constComp() >= e2 >= e3.constComp(); } + is >> std::ws; + if (is.get(x)) { + throw DataFormatError("Wrong variable bounds format"); + } } + lp.addRow(c); + return is; + } + + std::istream& readObjective(std::istream& is) { + is >> std::ws; + std::string sense; + is >> sense; + if (sense != "min" && sense != "max") { + throw DataFormatError("Wrong objective function format"); + } + LpSolverBase::Expr expr; + is >> std::ws; + readExpression(is, expr); + lp.setObj(expr); + if (sense == "min") { + lp.min(); + } else { + lp.max(); + } + return is; + } + + std::istream& readBounds(std::istream& is) { + LpSolverBase::Col c; + char x; + is >> std::ws; + if (!is.get(x)) { + throw DataFormatError("Wrong variable bounds format"); + } + if (varFirstChar(x)) { + is.putback(x); + readCol(is, c); + is >> std::ws; + Relation op1; + readRelation(is, op1); + double v; + readNum(is, v); + if (op1 == EQ) { + lp.colLowerBound(c, v); + lp.colUpperBound(c, v); + } else if (op1 == LE) { + lp.colUpperBound(c, v); + } else { + lp.colLowerBound(c, v); + } + is >> std::ws; + if (is.get(x)) { + throw DataFormatError("Wrong variable bounds format"); + } + } else { + is.putback(x); + double v; + readNum(is, v); + is >> std::ws; + Relation op1; + readRelation(is, op1); + is >> std::ws; + readCol(is, c); + is >> std::ws; + if (is.get(x)) { + is.putback(x); + is >> std::ws; + Relation op2; + readRelation(is, op2); + double w; + is >> std::ws; + readNum(is, w); + if (op2 != op1 || op1 == EQ) { + throw DataFormatError("Wrong range format"); + } + if (op1 == LE) { + lp.colLowerBound(c, v); + lp.colUpperBound(c, w); + } else { + lp.colLowerBound(c, w); + lp.colUpperBound(c, v); + } + if (is.get(x)) { + throw DataFormatError("Wrong variable bounds format"); + } + } else { + if (op1 == EQ) { + lp.colLowerBound(c, v); + lp.colUpperBound(c, v); + } else if (op1 == LE) { + lp.colLowerBound(c, v); + } else { + lp.colUpperBound(c, v); + } + } + } + return is; } std::istream& readExpression(std::istream& is, LpSolverBase::Expr& e) { @@ -277,40 +393,9 @@ static bool varChar(char c) { return (c >= '0' && c <= '9') || - (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); - } - - - void addConstraint(const LpSolverBase::Constr& constr) { - if (constr.expr().size() != 1) { - lp.addRow(constr); - } else { - Lp::Expr e = constr.expr(); - LpSolverBase::Col col = e.begin()->first; - double coeff = e.begin()->second; - double lb = LpSolverBase::NaN; - double ub = LpSolverBase::NaN; - if (coeff > 0) { - if (constr.upperBounded()) { - lb = (constr.lowerBound() - e.constComp()) / coeff; - } - if (constr.lowerBounded()) { - ub = (constr.upperBound() - e.constComp()) / coeff; - } - } else if (coeff < 0) { - if (constr.upperBounded()) { - lb = (constr.upperBound() - e.constComp()) / coeff; - } - if (constr.lowerBounded()) { - ub = (constr.lowerBound() - e.constComp()) / coeff; - } - } else { - lb = -LpSolverBase::INF; - ub = LpSolverBase::INF; - } - lp.colLowerBound(col, lb); - lp.colUpperBound(col, ub); - } + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '[' || c == ']'; } protected: @@ -320,26 +405,30 @@ /// It reads the content of the section. virtual void read(std::istream& is) { std::string line; + SubSection sub = CONSTRAINTS; while (getline(is, line)) { std::istringstream ls(line); - std::string sense; - ls >> sense; - if (sense == "min" || sense == "max") { - LpSolverBase::Expr expr; - ls >> std::ws; - readExpression(ls, expr); - lp.setObj(expr); - if (sense == "min") { - lp.min(); - } else { - lp.max(); - } + std::string type; + ls >> type; + if (type == "constraints") { + sub = CONSTRAINTS; + } else if (type == "bounds") { + sub = BOUNDS; + } else if (type == "objective") { + sub = OBJECTIVE; } else { ls.str(line); - LpSolverBase::Constr constr; - ls >> std::ws; - readConstraint(ls, constr); - addConstraint(constr); + switch (sub) { + case CONSTRAINTS: + readConstraint(ls); + break; + case BOUNDS: + readBounds(ls); + break; + case OBJECTIVE: + readObjective(ls); + break; + } } } } @@ -360,334 +449,177 @@ }; -// class LpWriter : public LemonWriter::SectionWriter { -// typedef LemonWriter::SectionWriter Parent; -// public: + class LpWriter : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + public: -// /// \brief Constructor. -// /// -// /// Constructor for LpWriter. It creates the LpWriter and attach -// /// it into the given LemonWriter. The lp writer will add -// /// variables, constraints and objective function to the -// /// given lp solver. -// LpWriter(LemonWriter& _writer, LpSolverBase& _lp, -// const std::string& _name = std::string()) -// : Parent(_writer), lp(_lp), name(_name) {} + /// \brief Constructor. + /// + /// Constructor for LpWriter. It creates the LpWriter and attach + /// it into the given LemonWriter. The lp writer will add + /// variables, constraints and objective function to the + /// given lp solver. + LpWriter(LemonWriter& _writer, LpSolverBase& _lp, + const std::string& _name = std::string()) + : Parent(_writer), lp(_lp), name(_name) {} -// /// \brief Destructor. -// /// -// /// Destructor for NodeSetWriter. -// virtual ~LpWriter() {} + /// \brief Destructor. + /// + /// Destructor for NodeSetWriter. + virtual ~LpWriter() {} -// private: -// LpWriter(const LpWriter&); -// void operator=(const LpWriter&); + private: + LpWriter(const LpWriter&); + void operator=(const LpWriter&); -// protected: + protected: -// /// \brief Gives back true when the SectionWriter can process -// /// the section with the given header line. -// /// -// /// It gives back the header line of the \c \@lp section. -// virtual std::string header() { -// std::ostringstream ls(line); -// ls << "@lp " << name; -// return ls.str(); -// } + /// \brief Gives back true when the SectionWriter can process + /// the section with the given header line. + /// + /// It gives back the header line of the \c \@lp section. + virtual std::string header() { + std::ostringstream ls; + ls << "@lp " << name; + return ls.str(); + } -// private: + private: -// std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) { -// char x; + void createCols() { + int num = 1; + std::map inverse; + + for (LpSolverBase::ColIt it(lp); it != INVALID; ++it) { + std::string name = lp.colName(it); + if (!name.empty() && inverse.find(name) == inverse.end()) { + cols.insert(std::make_pair(it, name)); + inverse.insert(std::make_pair(name, it)); + } else { + std::ostringstream ls; + ls << "var" << num; + ++num; + cols.insert(std::make_pair(it, ls.str())); + inverse.insert(std::make_pair(ls.str(), it)); + } + } + } + + void writeExpression(std::ostream& os, const LpSolverBase::Expr& e) { + bool first = true; + for (LpSolverBase::Expr::const_iterator jt = e.begin(); + jt != e.end(); ++jt) { + if (jt->second < 0.0) { + os << "- "; + if (jt->second != -1.0) { + os << -jt->second << " * "; + } + } else if (jt->second > 0.0) { + if (!first) { + os << "+ "; + } + if (jt->second != 1.0) { + os << jt->second << " * "; + } + } + first = false; + os << cols[jt->first] << " "; + } + if (e.constComp() < 0.0) { + os << "- " << -e.constComp() << " "; + } else if (e.constComp() > 0.0) { + if (!first) { + os << "+ "; + } + os << e.constComp() << " "; + } + } + + protected: + + /// \brief Writer function of the section. + /// + /// It writes the content of the section. + virtual void write(std::ostream& os) { + createCols(); + + os << "constraints" << std::endl; -// LpSolverBase::Expr e1, e2; -// Relation op1; -// is >> std::ws; -// writexpression(is, e1); -// is >> std::ws; -// writeRelation(is, op1); -// is >> std::ws; -// writexpression(is, e2); -// if (!is.get(x)) { -// if (op1 == LE) { -// c = e1 <= e2; -// } else if (op1 == GE) { -// c = e1 >= e2; -// } else { -// c = e1 == e2; -// } -// } else { -// is.putback(x); -// LpSolverBase::Expr e3; -// Relation op2; -// writeRelation(is, op2); -// is >> std::ws; -// writexpression(is, e3); -// if (!e1.empty() || !e3.empty()) { -// throw DataFormatError("Wrong range format"); -// } -// if (op2 != op1 || op1 == EQ) { -// throw DataFormatError("Wrong range format"); -// } -// if (op1 == LE) { -// c = e1.constComp() <= e2 <= e3.constComp(); -// } else { -// c = e1.constComp() >= e2 >= e3.constComp(); -// } -// } -// } + for (LpSolverBase::RowIt it(lp); it != INVALID; ++it) { + double lower, upper; + lp.getRowBounds(it, lower, upper); + if (lower == -LpSolverBase::INF && upper == LpSolverBase::INF) + continue; + os << " "; + + if (lower != upper) { + if (lower != -LpSolverBase::INF) { + os << lower << " <= "; + } + + writeExpression(os, lp.row(it)); + + if (upper != LpSolverBase::INF) { + os << "<= " << upper << " "; + } + } else { -// std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) { -// LpSolverBase::Col c; -// double d; -// char x; -// writelement(is, c, d); -// if (c != INVALID) { -// e += d * c; -// } else { -// e += d; -// } -// is >> std::ws; -// while (is.get(x) && (x == '+' || x == '-')) { -// is >> std::ws; -// writelement(is, c, d); -// if (c != INVALID) { -// e += (x == '+' ? d : -d) * c; -// } else { -// e += (x == '+' ? d : -d); -// } -// is >> std::ws; -// } -// if (!is) { -// is.clear(); -// } else { -// is.putback(x); -// } -// return is; -// } + writeExpression(os, lp.row(it)); + os << "== " << upper << " "; + + } -// std::ostream& writelement(std::ostream& is, -// LpSolverBase::Col& c, double& d) { -// d = 1.0; -// c = INVALID; -// char x, y; -// if (!is.get(x)) throw DataFormatError("Cannot find lp element"); -// if (x == '+' || x == '-') { -// is >> std::ws; -// d *= x == '-' ? -1 : 1; -// while (is.get(x) && (x == '+' || x == '-')) { -// d *= x == '-' ? -1 : 1; -// is >> std::ws; -// } -// if (!is) throw DataFormatError("Cannot find lp element"); -// } -// if (numFirstChar(x)) { -// is.putback(x); -// double e; -// writeNum(is, e); -// d *= e; -// } else if (varFirstChar(x)) { -// is.putback(x); -// LpSolverBase::Col f; -// writeCol(is, f); -// c = f; -// } else { -// throw DataFormatError("Invalid expression format"); -// } -// is >> std::ws; -// while (is.get(y) && (y == '*' || y == '/')) { -// is >> std::ws; -// if (!is.get(x)) throw DataFormatError("Cannot find lp element"); -// if (x == '+' || x == '-') { -// is >> std::ws; -// d *= x == '-' ? -1 : 1; -// while (is.get(x) && (x == '+' || x == '-')) { -// d *= x == '-' ? -1 : 1; -// is >> std::ws; -// } -// if (!is) throw DataFormatError("Cannot find lp element"); -// } -// if (numFirstChar(x)) { -// is.putback(x); -// double e; -// writeNum(is, e); -// if (y == '*') { -// d *= e; -// } else { -// d /= e; -// } -// } else if (varFirstChar(x)) { -// is.putback(x); -// LpSolverBase::Col f; -// writeCol(is, f); -// if (y == '*') { -// if (c == INVALID) { -// c = f; -// } else { -// throw DataFormatError("Quadratic element in expression"); -// } -// } else { -// throw DataFormatError("Division by variable"); -// } -// } else { -// throw DataFormatError("Invalid expression format"); -// } -// is >> std::ws; -// } -// if (!is) { -// is.clear(); -// } else { -// is.putback(y); -// } -// return is; -// } + os << std::endl; + } -// std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) { -// char x; -// std::string var; -// while (is.get(x) && varChar(x)) { -// var += x; -// } -// if (!is) { -// is.clear(); -// } else { -// is.putback(x); -// } -// ColMap::const_iterator it = cols.find(var); -// if (cols.find(var) != cols.end()) { -// c = it->second; -// } else { -// c = lp.addCol(); -// cols.insert(std::make_pair(var, c)); -// lp.colName(c, var); -// } -// return is; -// } + os << "bounds" << std::endl; + + for (LpSolverBase::ColIt it(lp); it != INVALID; ++it) { + double lower = lp.colLowerBound(it); + double upper = lp.colUpperBound(it); + if (lower == -LpSolverBase::INF && upper == LpSolverBase::INF) + continue; + os << " "; -// std::ostream& writeNum(std::ostream& is, double& d) { -// is >> d; -// if (!is) throw DataFormatError("Wrong number format"); -// return is; -// } + if (lower != upper) { + if (lower != -LpSolverBase::INF) { + os << lower << " <= "; + } + + os << cols[it] << " "; + + if (upper != LpSolverBase::INF) { + os << "<= " << upper << " "; + } + } else { + os << cols[it] << " == " << upper << " "; + } + os << std::endl; + } -// std::ostream& writeRelation(std::ostream& is, Relation& op) { -// char x, y; -// if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) { -// throw DataFormatError("Wrong relation operator"); -// } -// if (!is.get(y) || y != '=') { -// throw DataFormatError("Wrong relation operator"); -// } -// switch (x) { -// case '<': op = LE; -// break; -// case '=': op = EQ; -// break; -// case '>': op = GE; -// break; -// } -// return is; -// } + os << "objective" << std::endl; + os << " "; + if (lp.is_min()) { + os << "min "; + } else { + os << "max "; + } + writeExpression(os, lp.obj()); + os << std::endl; + } + -// static bool relationFirstChar(char c) { -// return c == '<' || c == '=' || c == '>'; -// } + private: -// static bool varFirstChar(char c) { -// return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -// } - -// static bool numFirstChar(char c) { -// return (c >= '0' && c <= '9') || c == '.'; -// } - -// static bool varChar(char c) { -// return (c >= '0' && c <= '9') || -// (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -// } - - -// void addConstraint(const LpSolverBase::Constr& constr) { -// if (constr.expr().size() != 1) { -// lp.addRow(constr); -// } else { -// Lp::Expr e = constr.expr(); -// LpSolverBase::Col col = e.begin()->first; -// double coeff = e.begin()->second; -// double lb = LpSolverBase::NaN; -// double ub = LpSolverBase::NaN; -// if (coeff > 0) { -// if (constr.upperBounded()) { -// lb = (constr.lowerBound() - e.constComp()) / coeff; -// } -// if (constr.lowerBounded()) { -// ub = (constr.upperBound() - e.constComp()) / coeff; -// } -// } else if (coeff < 0) { -// if (constr.upperBounded()) { -// lb = (constr.upperBound() - e.constComp()) / coeff; -// } -// if (constr.lowerBounded()) { -// ub = (constr.lowerBound() - e.constComp()) / coeff; -// } -// } else { -// lb = -LpSolverBase::INF; -// ub = LpSolverBase::INF; -// } -// lp.colLowerBound(col, lb); -// lp.colUpperBound(col, ub); -// } -// } - -// protected: - -// /// \brief Writer function of the section. -// /// -// /// It writes the content of the section. -// virtual void write(std::ostream& is) { -// std::string line; -// std::map vars; -// while (getline(is, line)) { -// std::istringstream ls(line); -// std::string sense; -// ls >> sense; -// if (sense == "min" || sense == "max") { -// LpSolverBase::Expr expr; -// ls >> std::ws; -// writeExpression(ls, expr); -// lp.setObj(expr); -// if (sense == "min") { -// lp.min(); -// } else { -// lp.max(); -// } -// } else { -// ls.str(line); -// LpSolverBase::Constr constr; -// ls >> std::ws; -// writeConstraint(ls, constr); -// addConstraint(constr); -// } -// } -// } + typedef std::map ColMap; -// virtual void missing() { -// ErrorMessage msg; -// msg << "Lp section not found in file: @lp " << name; -// throw IoParameterError(msg.message()); -// } - -// private: - -// typedef std::map ColMap; - -// LpSolverBase& lp; -// std::string name; -// ColMap cols; -// }; + LpSolverBase& lp; + std::string name; + ColMap cols; + }; }