# HG changeset patch # User alpar # Date 1111776967 0 # Node ID 92ba3e62825d45b9dfd9f53cf399dbccab82d7f8 # Parent a490938ad0aa8d92a0ba76cd8e549c54143e77a6 Constraints (expressions containing <= or >=) can be passed to addRow() and setRow() diff -r a490938ad0aa -r 92ba3e62825d src/work/athos/lp/lin_expr.h --- a/src/work/athos/lp/lin_expr.h Fri Mar 25 16:19:03 2005 +0000 +++ b/src/work/athos/lp/lin_expr.h Fri Mar 25 18:56:07 2005 +0000 @@ -18,10 +18,8 @@ #define LEMON_LIN_EXPR_H #include - - #include - +#include ///\file ///\brief Classes to handle linear expressions namespace lemon { @@ -39,6 +37,7 @@ Coeff const_comp; public: + typedef True IsLinExpression; ///\e SparseLinExpr() : Base(), const_comp(0) { } ///\e @@ -262,6 +261,50 @@ ///\relates SparseLinExpr /// template + SparseLinExpr operator+(const V &v,const typename V::ExprValue &c) { + SparseLinExpr tmp(v); + tmp.constComp()=c; + return tmp; + } + + ///\e + + ///\relates SparseLinExpr + /// + template + SparseLinExpr operator-(const V &v,const typename V::ExprValue &c) { + SparseLinExpr tmp(v); + tmp.constComp()=-c; + return tmp; + } + + ///\e + + ///\relates SparseLinExpr + /// + template + SparseLinExpr operator+(const typename V::ExprValue &c,const V &v) { + SparseLinExpr tmp(v); + tmp.constComp()=c; + return tmp; + } + + ///\e + + ///\relates SparseLinExpr + /// + template + SparseLinExpr operator-(const typename V::ExprValue &c,const V &v) { + SparseLinExpr tmp(c); + tmp[v]=-1; + return tmp; + } + + ///\e + + ///\relates SparseLinExpr + /// + template SparseLinExpr operator+(const V &v1,const V &v2) { SparseLinExpr tmp(v1); tmp[v2]+=1; @@ -302,6 +345,154 @@ } + ////////////////////////////////////////////////////////////////////// + /// Constraints + ////////////////////////////////////////////////////////////////////// + + template + class LinConstr + { + public: + typedef E Expr; + typedef typename E::Var Var; + typedef typename E::Coeff Coeff; + + static const Coeff INF; + static const Coeff NaN; +// static const Coeff INF=0; +// static const Coeff NaN=1; + + Expr expr; + Coeff lb,ub; + + LinConstr() : expr(), lb(NaN), ub(NaN) {} + LinConstr(Coeff _lb,const Expr &e,Coeff _ub) : + expr(e), lb(_lb), ub(_ub) {} + LinConstr(const Expr &e,Coeff _ub) : + expr(e), lb(NaN), ub(_ub) {} + LinConstr(Coeff _lb,const Expr &e) : + expr(e), lb(_lb), ub(NaN) {} + }; + + template + const typename LinConstr::Coeff LinConstr::INF= + std::numeric_limits::infinity(); + template + const typename LinConstr::Coeff LinConstr::NaN= + std::numeric_limits::quiet_NaN(); + + + template + typename enable_if >::type + operator<=(const E &e,const E &f) + { + return LinConstr(-LinConstr::INF,e-f,0); + } + + template + typename enable_if >::type + operator>=(const E &e,const E &f) + { + return LinConstr(-LinConstr::INF,f-e,0); + } + + template + typename enable_if >::type + operator==(const E &e,const E &f) + { + return LinConstr(0,e-f,0); + } + + ////////////////////////////// + + template + typename enable_if >::type + operator<=(const E &e,const typename E::Coeff &n) + { + return LinConstr(e,n); + } + + template + typename enable_if >::type + operator>=(const E &e,const typename E::Coeff &n) + { + return LinConstr(n,e); + } + + template + typename enable_if >::type + operator==(const E &e,const typename E::Coeff &n) + { + return LinConstr(n,e,n); + } + + ////////////////////////////// + + template + typename enable_if >::type + operator<=(const typename E::Coeff &n,const E &e) + { + return LinConstr(n,e); + } + + template + typename enable_if >::type + operator>=(const typename E::Coeff &n,const E &e) + { + return LinConstr(e,n); + } + + template + typename enable_if >::type + operator==(const typename E::Coeff &n,const E &e) + { + return LinConstr(n,e,n); + } + + ////////////////////////////// + + template + typename enable_if >::type + operator<=(const typename E::Coeff &n,const LinConstr &c) + { + LinConstr tmp(c); + if(tmp.lb!=tmp.NaN) throw LogicError(); + else tmp.lb=n; + return tmp; + } + + template + typename enable_if >::type + operator>=(const typename E::Coeff &n,const LinConstr &c) + { + LinConstr tmp(c); + if(tmp.ub!=tmp.NaN) throw LogicError(); + else tmp.ub=n; + return tmp; + } + + template + typename enable_if >::type + operator<=(const LinConstr &c,const typename E::Coeff &n) + { + LinConstr tmp(c); + if(tmp.ub!=tmp.NaN) throw LogicError(); + else tmp.ub=n; + return tmp; + } + + template + typename enable_if >::type + operator>=(const LinConstr &c,const typename E::Coeff &n) + { + LinConstr tmp(c); + if(tmp.lb!=tmp.NaN) throw LogicError(); + else tmp.lb=n; + return tmp; + } + + + } //namespace lemon #endif //LEMON_LIN_EXPR_H diff -r a490938ad0aa -r 92ba3e62825d src/work/athos/lp/lp_base.cc --- a/src/work/athos/lp/lp_base.cc Fri Mar 25 16:19:03 2005 +0000 +++ b/src/work/athos/lp/lp_base.cc Fri Mar 25 18:56:07 2005 +0000 @@ -22,6 +22,8 @@ const LpSolverBase::Value LpSolverBase::INF = std::numeric_limits::infinity(); + const LpSolverBase::Value + LpSolverBase::NaN = std::numeric_limits::quiet_NaN(); } //namespace lemon diff -r a490938ad0aa -r 92ba3e62825d src/work/athos/lp/lp_base.h --- a/src/work/athos/lp/lp_base.h Fri Mar 25 16:19:03 2005 +0000 +++ b/src/work/athos/lp/lp_base.h Fri Mar 25 18:56:07 2005 +0000 @@ -116,6 +116,8 @@ typedef double Value; ///The infinity constant static const Value INF; + ///The not a number constant + static const Value NaN; ///Refer to a column of the LP. @@ -167,6 +169,8 @@ ///Linear expression typedef SparseLinExpr Expr; + ///Linear constraint + typedef LinConstr Constr; protected: _FixId rows; @@ -318,6 +322,18 @@ _setRowUpperBound(rows.floatingId(r.id),u-e.constComp()); } + ///Set a row (i.e a constaint) of the LP + + ///\param r is the row to be modified + ///\param c is a linear expression (see \ref Constr) + ///\bug This is a temportary function. The interface will change to + ///a better one. + void setRow(Row r, const Constr &c) { + Value lb= c.lb==NaN?-INF:lb; + Value ub= c.ub==NaN?INF:lb; + setRow(r,lb,c.expr,ub); + } + ///Add a new row (i.e a new constaint) to the LP ///\param l is the lower bound (-\ref INF means no bound) @@ -332,6 +348,18 @@ return r; } + ///Add a new row (i.e a new constaint) to the LP + + ///\param c is a linear expression (see \ref Constr) + ///\return The created row. + ///\bug This is a temportary function. The interface will change to + ///a better one. + Row addRow(const Constr &c) { + Row r=addRow(); + setRow(r,c); + return r; + } + /// Set the lower bound of a column (i.e a variable) /// The upper bound of a variable (column) have to be given by an diff -r a490938ad0aa -r 92ba3e62825d src/work/athos/lp/lp_test.cc --- a/src/work/athos/lp/lp_test.cc Fri Mar 25 16:19:03 2005 +0000 +++ b/src/work/athos/lp/lp_test.cc Fri Mar 25 18:56:07 2005 +0000 @@ -1,5 +1,6 @@ #include"lp_solver_skeleton.h" #include"lp_glpk.h" +#include using namespace lemon; @@ -36,9 +37,52 @@ lp.addRow(LP::INF,3.0*(x[1]+x[2]/2)-x[3],23); lp.addRow(LP::INF,3.0*(p1+p2*2-5*p3+12-p4/3)+2*p4-4,23); lp.addRow(LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23); + + lp.addRow(x[1]+x[3]<=x[5]-3); + lp.addRow(-7<=x[1]+x[3]-12<=3); } +template +double maxFlow(const G &g,const C &cap,typename G::Node s,typename G::Node t) +{ + LpGlpk lp; + + typedef G Graph; + typedef typename G::Node Node; + typedef typename G::NodeIt NodeIt; + typedef typename G::Edge Edge; + typedef typename G::EdgeIt EdgeIt; + typedef typename G::OutEdgeIt OutEdgeIt; + typedef typename G::InEdgeIt InEdgeIt; + + typename G::EdgeMap x(g); + // lp.addColSet(x); + for(EdgeIt e(g);e!=INVALID;++e) x[e]=lp.addCol(); + + for(EdgeIt e(g);e!=INVALID;++e) { + lp.setColUpperBound(x[e],cap[e]); + lp.setColLowerBound(x[e],0); + } + + for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) { + LpGlpk::Expr ex; + for(InEdgeIt e(g,n);e!=INVALID;++e) ex+=x[e]; + for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e]; + lp.addRow(0,ex,0); + } + { + LpGlpk::Expr ex; + for(InEdgeIt e(g,t);e!=INVALID;++e) ex+=x[e]; + for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e]; + lp.setObj(ex); + } + + lp.solve(); + + return 0; +} + int main() { LpSolverSkeleton lp_skel; @@ -46,4 +90,10 @@ lpTest(lp_skel); lpTest(lp_glpk); + + ListGraph g; + ListGraph::EdgeMap cap(g); + + maxFlow(g,cap,ListGraph::NodeIt(g),ListGraph::NodeIt(g)); + }