[Lemon-commits] deba: r3175 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Thu Feb 15 20:15:15 CET 2007
Author: deba
Date: Thu Feb 15 20:15:14 2007
New Revision: 3175
Modified:
hugo/trunk/lemon/lp_base.h
hugo/trunk/lemon/lp_cplex.cc
hugo/trunk/lemon/lp_cplex.h
hugo/trunk/lemon/lp_glpk.cc
hugo/trunk/lemon/lp_glpk.h
hugo/trunk/lemon/lp_skeleton.cc
hugo/trunk/lemon/lp_skeleton.h
hugo/trunk/lemon/lp_soplex.cc
hugo/trunk/lemon/lp_soplex.h
hugo/trunk/lemon/lp_utils.h
Log:
Lp row and col getter function
lp section reader and writer for lemon IO
Modified: hugo/trunk/lemon/lp_base.h
==============================================================================
--- hugo/trunk/lemon/lp_base.h (original)
+++ hugo/trunk/lemon/lp_base.h Thu Feb 15 20:15:14 2007
@@ -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 <typename _Base>
- class MappedIterator {
+ template <typename _Expr>
+ class MappedOutputIterator {
+ public:
+
+ 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<int, Value>& 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 <typename Expr>
+ class MappedInputIterator {
public:
- typedef _Base Base;
+ 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<Expr::const_iterator> LpRowIterator;
+ typedef MappedInputIterator<Expr> ConstRowIterator;
/// STL compatible iterator for lp row
- typedef MappedIterator<DualExpr::const_iterator> LpColIterator;
+ typedef MappedInputIterator<DualExpr> ConstColIterator;
+
+ /// STL compatible iterator for lp col
+ typedef MappedOutputIterator<Expr> RowIterator;
+ /// STL compatible iterator for lp row
+ typedef MappedOutputIterator<DualExpr> 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
Modified: hugo/trunk/lemon/lp_cplex.cc
==============================================================================
--- hugo/trunk/lemon/lp_cplex.cc (original)
+++ hugo/trunk/lemon/lp_cplex.cc Thu Feb 15 20:15:14 2007
@@ -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<int> indices;
std::vector<int> rowlist;
std::vector<Value> 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<int> indices;
std::vector<int> collist;
std::vector<Value> 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)
{
Modified: hugo/trunk/lemon/lp_cplex.h
==============================================================================
--- hugo/trunk/lemon/lp_cplex.h (original)
+++ hugo/trunk/lemon/lp_cplex.h Thu Feb 15 20:15:14 2007
@@ -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);
Modified: hugo/trunk/lemon/lp_glpk.cc
==============================================================================
--- hugo/trunk/lemon/lp_glpk.cc (original)
+++ hugo/trunk/lemon/lp_glpk.cc Thu Feb 15 20:15:14 2007
@@ -126,7 +126,7 @@
}
- void LpGlpk::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e)
+ void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
{
std::vector<int> indices;
std::vector<Value> 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<int> indices(length + 1);
+ std::vector<Value> 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<int> indices;
std::vector<Value> 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<int> indices(length + 1);
+ std::vector<Value> 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<int> indices(length + 2);
- std::vector<Value> values(length + 2);
+ std::vector<int> indices(length + 1);
+ std::vector<Value> values(length + 1);
lpx_get_mat_row(lp, row, &indices[0], &values[0]);
Modified: hugo/trunk/lemon/lp_glpk.h
==============================================================================
--- hugo/trunk/lemon/lp_glpk.h (original)
+++ hugo/trunk/lemon/lp_glpk.h Thu Feb 15 20:15:14 2007
@@ -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);
Modified: hugo/trunk/lemon/lp_skeleton.cc
==============================================================================
--- hugo/trunk/lemon/lp_skeleton.cc (original)
+++ hugo/trunk/lemon/lp_skeleton.cc Thu Feb 15 20:15:14 2007
@@ -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 )
Modified: hugo/trunk/lemon/lp_skeleton.h
==============================================================================
--- hugo/trunk/lemon/lp_skeleton.h (original)
+++ hugo/trunk/lemon/lp_skeleton.h Thu Feb 15 20:15:14 2007
@@ -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);
Modified: hugo/trunk/lemon/lp_soplex.cc
==============================================================================
--- hugo/trunk/lemon/lp_soplex.cc (original)
+++ hugo/trunk/lemon/lp_soplex.cc Thu Feb 15 20:15:14 2007
@@ -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);
Modified: hugo/trunk/lemon/lp_soplex.h
==============================================================================
--- hugo/trunk/lemon/lp_soplex.h (original)
+++ hugo/trunk/lemon/lp_soplex.h Thu Feb 15 20:15:14 2007
@@ -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);
Modified: hugo/trunk/lemon/lp_utils.h
==============================================================================
--- hugo/trunk/lemon/lp_utils.h (original)
+++ hugo/trunk/lemon/lp_utils.h Thu Feb 15 20:15:14 2007
@@ -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:
-
-
-// /// \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() {}
-
-// private:
-// LpWriter(const LpWriter&);
-// void operator=(const LpWriter&);
+ 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 Destructor.
+ ///
+ /// Destructor for NodeSetWriter.
+ virtual ~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:
+ void createCols() {
+ int num = 1;
-// std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) {
-// char x;
+ std::map<std::string, LpSolverBase::Col> inverse;
-
-// 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();
-// }
-// }
-// }
-
-// 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;
-// }
-
-// 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;
-// }
-
-// 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;
-// }
-
-// std::ostream& writeNum(std::ostream& is, double& d) {
-// is >> d;
-// if (!is) throw DataFormatError("Wrong number format");
-// return is;
-// }
-
-// 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;
-// }
-
-// static bool relationFirstChar(char c) {
-// return c == '<' || c == '=' || c == '>';
-// }
-
-// 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);
-// }
-// }
+ 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));
+ }
+ }
+ }
-// protected:
+ 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() << " ";
+ }
+ }
-// /// \brief Writer function of the section.
-// ///
-// /// It writes the content of the section.
-// virtual void write(std::ostream& is) {
-// std::string line;
-// std::map<std::string, LpSolverBase::Col> 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);
-// }
-// }
-// }
+ 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;
+
+ 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 {
+
+ writeExpression(os, lp.row(it));
+ os << "== " << upper << " ";
+
+ }
+
+ os << std::endl;
+ }
+
+ 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 << " ";
+
+ 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;
+ }
+
+ os << "objective" << std::endl;
+ os << " ";
+ if (lp.is_min()) {
+ os << "min ";
+ } else {
+ os << "max ";
+ }
+ writeExpression(os, lp.obj());
+ os << std::endl;
+ }
-// virtual void missing() {
-// ErrorMessage msg;
-// msg << "Lp section not found in file: @lp " << name;
-// throw IoParameterError(msg.message());
-// }
-// private:
+ private:
-// typedef std::map<std::string, LpSolverBase::Col> ColMap;
+ typedef std::map<LpSolverBase::Col, std::string> ColMap;
-// LpSolverBase& lp;
-// std::string name;
-// ColMap cols;
-// };
+ LpSolverBase& lp;
+ std::string name;
+ ColMap cols;
+ };
}
More information about the Lemon-commits
mailing list