1.1 --- a/src/work/athos/lp/lin_expr.h Fri Mar 25 16:19:03 2005 +0000
1.2 +++ b/src/work/athos/lp/lin_expr.h Fri Mar 25 18:56:07 2005 +0000
1.3 @@ -18,10 +18,8 @@
1.4 #define LEMON_LIN_EXPR_H
1.5
1.6 #include<vector>
1.7 -
1.8 -
1.9 #include<map>
1.10 -
1.11 +#include<lemon/utility.h>
1.12 ///\file
1.13 ///\brief Classes to handle linear expressions
1.14 namespace lemon {
1.15 @@ -39,6 +37,7 @@
1.16
1.17 Coeff const_comp;
1.18 public:
1.19 + typedef True IsLinExpression;
1.20 ///\e
1.21 SparseLinExpr() : Base(), const_comp(0) { }
1.22 ///\e
1.23 @@ -262,6 +261,50 @@
1.24 ///\relates SparseLinExpr
1.25 ///
1.26 template <class V>
1.27 + SparseLinExpr<V> operator+(const V &v,const typename V::ExprValue &c) {
1.28 + SparseLinExpr<V> tmp(v);
1.29 + tmp.constComp()=c;
1.30 + return tmp;
1.31 + }
1.32 +
1.33 + ///\e
1.34 +
1.35 + ///\relates SparseLinExpr
1.36 + ///
1.37 + template <class V>
1.38 + SparseLinExpr<V> operator-(const V &v,const typename V::ExprValue &c) {
1.39 + SparseLinExpr<V> tmp(v);
1.40 + tmp.constComp()=-c;
1.41 + return tmp;
1.42 + }
1.43 +
1.44 + ///\e
1.45 +
1.46 + ///\relates SparseLinExpr
1.47 + ///
1.48 + template <class V>
1.49 + SparseLinExpr<V> operator+(const typename V::ExprValue &c,const V &v) {
1.50 + SparseLinExpr<V> tmp(v);
1.51 + tmp.constComp()=c;
1.52 + return tmp;
1.53 + }
1.54 +
1.55 + ///\e
1.56 +
1.57 + ///\relates SparseLinExpr
1.58 + ///
1.59 + template <class V>
1.60 + SparseLinExpr<V> operator-(const typename V::ExprValue &c,const V &v) {
1.61 + SparseLinExpr<V> tmp(c);
1.62 + tmp[v]=-1;
1.63 + return tmp;
1.64 + }
1.65 +
1.66 + ///\e
1.67 +
1.68 + ///\relates SparseLinExpr
1.69 + ///
1.70 + template <class V>
1.71 SparseLinExpr<V> operator+(const V &v1,const V &v2) {
1.72 SparseLinExpr<V> tmp(v1);
1.73 tmp[v2]+=1;
1.74 @@ -302,6 +345,154 @@
1.75 }
1.76
1.77
1.78 + //////////////////////////////////////////////////////////////////////
1.79 + /// Constraints
1.80 + //////////////////////////////////////////////////////////////////////
1.81 +
1.82 + template <class E>
1.83 + class LinConstr
1.84 + {
1.85 + public:
1.86 + typedef E Expr;
1.87 + typedef typename E::Var Var;
1.88 + typedef typename E::Coeff Coeff;
1.89 +
1.90 + static const Coeff INF;
1.91 + static const Coeff NaN;
1.92 +// static const Coeff INF=0;
1.93 +// static const Coeff NaN=1;
1.94 +
1.95 + Expr expr;
1.96 + Coeff lb,ub;
1.97 +
1.98 + LinConstr() : expr(), lb(NaN), ub(NaN) {}
1.99 + LinConstr(Coeff _lb,const Expr &e,Coeff _ub) :
1.100 + expr(e), lb(_lb), ub(_ub) {}
1.101 + LinConstr(const Expr &e,Coeff _ub) :
1.102 + expr(e), lb(NaN), ub(_ub) {}
1.103 + LinConstr(Coeff _lb,const Expr &e) :
1.104 + expr(e), lb(_lb), ub(NaN) {}
1.105 + };
1.106 +
1.107 + template<class E>
1.108 + const typename LinConstr<E>::Coeff LinConstr<E>::INF=
1.109 + std::numeric_limits<Coeff>::infinity();
1.110 + template<class E>
1.111 + const typename LinConstr<E>::Coeff LinConstr<E>::NaN=
1.112 + std::numeric_limits<Coeff>::quiet_NaN();
1.113 +
1.114 +
1.115 + template<class E>
1.116 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.117 + operator<=(const E &e,const E &f)
1.118 + {
1.119 + return LinConstr<E>(-LinConstr<E>::INF,e-f,0);
1.120 + }
1.121 +
1.122 + template<class E>
1.123 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.124 + operator>=(const E &e,const E &f)
1.125 + {
1.126 + return LinConstr<E>(-LinConstr<E>::INF,f-e,0);
1.127 + }
1.128 +
1.129 + template<class E>
1.130 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.131 + operator==(const E &e,const E &f)
1.132 + {
1.133 + return LinConstr<E>(0,e-f,0);
1.134 + }
1.135 +
1.136 + //////////////////////////////
1.137 +
1.138 + template<class E>
1.139 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.140 + operator<=(const E &e,const typename E::Coeff &n)
1.141 + {
1.142 + return LinConstr<E>(e,n);
1.143 + }
1.144 +
1.145 + template<class E>
1.146 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.147 + operator>=(const E &e,const typename E::Coeff &n)
1.148 + {
1.149 + return LinConstr<E>(n,e);
1.150 + }
1.151 +
1.152 + template<class E>
1.153 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.154 + operator==(const E &e,const typename E::Coeff &n)
1.155 + {
1.156 + return LinConstr<E>(n,e,n);
1.157 + }
1.158 +
1.159 + //////////////////////////////
1.160 +
1.161 + template<class E>
1.162 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.163 + operator<=(const typename E::Coeff &n,const E &e)
1.164 + {
1.165 + return LinConstr<E>(n,e);
1.166 + }
1.167 +
1.168 + template<class E>
1.169 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.170 + operator>=(const typename E::Coeff &n,const E &e)
1.171 + {
1.172 + return LinConstr<E>(e,n);
1.173 + }
1.174 +
1.175 + template<class E>
1.176 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.177 + operator==(const typename E::Coeff &n,const E &e)
1.178 + {
1.179 + return LinConstr<E>(n,e,n);
1.180 + }
1.181 +
1.182 + //////////////////////////////
1.183 +
1.184 + template<class E>
1.185 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.186 + operator<=(const typename E::Coeff &n,const LinConstr<E> &c)
1.187 + {
1.188 + LinConstr<E> tmp(c);
1.189 + if(tmp.lb!=tmp.NaN) throw LogicError();
1.190 + else tmp.lb=n;
1.191 + return tmp;
1.192 + }
1.193 +
1.194 + template<class E>
1.195 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.196 + operator>=(const typename E::Coeff &n,const LinConstr<E> &c)
1.197 + {
1.198 + LinConstr<E> tmp(c);
1.199 + if(tmp.ub!=tmp.NaN) throw LogicError();
1.200 + else tmp.ub=n;
1.201 + return tmp;
1.202 + }
1.203 +
1.204 + template<class E>
1.205 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.206 + operator<=(const LinConstr<E> &c,const typename E::Coeff &n)
1.207 + {
1.208 + LinConstr<E> tmp(c);
1.209 + if(tmp.ub!=tmp.NaN) throw LogicError();
1.210 + else tmp.ub=n;
1.211 + return tmp;
1.212 + }
1.213 +
1.214 + template<class E>
1.215 + typename enable_if<typename E::IsLinExpression, LinConstr<E> >::type
1.216 + operator>=(const LinConstr<E> &c,const typename E::Coeff &n)
1.217 + {
1.218 + LinConstr<E> tmp(c);
1.219 + if(tmp.lb!=tmp.NaN) throw LogicError();
1.220 + else tmp.lb=n;
1.221 + return tmp;
1.222 + }
1.223 +
1.224 +
1.225 +
1.226 } //namespace lemon
1.227
1.228 #endif //LEMON_LIN_EXPR_H
2.1 --- a/src/work/athos/lp/lp_base.cc Fri Mar 25 16:19:03 2005 +0000
2.2 +++ b/src/work/athos/lp/lp_base.cc Fri Mar 25 18:56:07 2005 +0000
2.3 @@ -22,6 +22,8 @@
2.4
2.5 const LpSolverBase::Value
2.6 LpSolverBase::INF = std::numeric_limits<Value>::infinity();
2.7 + const LpSolverBase::Value
2.8 + LpSolverBase::NaN = std::numeric_limits<Value>::quiet_NaN();
2.9
2.10
2.11 } //namespace lemon
3.1 --- a/src/work/athos/lp/lp_base.h Fri Mar 25 16:19:03 2005 +0000
3.2 +++ b/src/work/athos/lp/lp_base.h Fri Mar 25 18:56:07 2005 +0000
3.3 @@ -116,6 +116,8 @@
3.4 typedef double Value;
3.5 ///The infinity constant
3.6 static const Value INF;
3.7 + ///The not a number constant
3.8 + static const Value NaN;
3.9
3.10 ///Refer to a column of the LP.
3.11
3.12 @@ -167,6 +169,8 @@
3.13
3.14 ///Linear expression
3.15 typedef SparseLinExpr<Col> Expr;
3.16 + ///Linear constraint
3.17 + typedef LinConstr<Expr> Constr;
3.18
3.19 protected:
3.20 _FixId rows;
3.21 @@ -318,6 +322,18 @@
3.22 _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
3.23 }
3.24
3.25 + ///Set a row (i.e a constaint) of the LP
3.26 +
3.27 + ///\param r is the row to be modified
3.28 + ///\param c is a linear expression (see \ref Constr)
3.29 + ///\bug This is a temportary function. The interface will change to
3.30 + ///a better one.
3.31 + void setRow(Row r, const Constr &c) {
3.32 + Value lb= c.lb==NaN?-INF:lb;
3.33 + Value ub= c.ub==NaN?INF:lb;
3.34 + setRow(r,lb,c.expr,ub);
3.35 + }
3.36 +
3.37 ///Add a new row (i.e a new constaint) to the LP
3.38
3.39 ///\param l is the lower bound (-\ref INF means no bound)
3.40 @@ -332,6 +348,18 @@
3.41 return r;
3.42 }
3.43
3.44 + ///Add a new row (i.e a new constaint) to the LP
3.45 +
3.46 + ///\param c is a linear expression (see \ref Constr)
3.47 + ///\return The created row.
3.48 + ///\bug This is a temportary function. The interface will change to
3.49 + ///a better one.
3.50 + Row addRow(const Constr &c) {
3.51 + Row r=addRow();
3.52 + setRow(r,c);
3.53 + return r;
3.54 + }
3.55 +
3.56 /// Set the lower bound of a column (i.e a variable)
3.57
3.58 /// The upper bound of a variable (column) have to be given by an
4.1 --- a/src/work/athos/lp/lp_test.cc Fri Mar 25 16:19:03 2005 +0000
4.2 +++ b/src/work/athos/lp/lp_test.cc Fri Mar 25 18:56:07 2005 +0000
4.3 @@ -1,5 +1,6 @@
4.4 #include"lp_solver_skeleton.h"
4.5 #include"lp_glpk.h"
4.6 +#include<lemon/list_graph.h>
4.7
4.8 using namespace lemon;
4.9
4.10 @@ -36,9 +37,52 @@
4.11 lp.addRow(LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
4.12 lp.addRow(LP::INF,3.0*(p1+p2*2-5*p3+12-p4/3)+2*p4-4,23);
4.13 lp.addRow(LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
4.14 +
4.15 + lp.addRow(x[1]+x[3]<=x[5]-3);
4.16 + lp.addRow(-7<=x[1]+x[3]-12<=3);
4.17 }
4.18
4.19
4.20 +template<class G,class C>
4.21 +double maxFlow(const G &g,const C &cap,typename G::Node s,typename G::Node t)
4.22 +{
4.23 + LpGlpk lp;
4.24 +
4.25 + typedef G Graph;
4.26 + typedef typename G::Node Node;
4.27 + typedef typename G::NodeIt NodeIt;
4.28 + typedef typename G::Edge Edge;
4.29 + typedef typename G::EdgeIt EdgeIt;
4.30 + typedef typename G::OutEdgeIt OutEdgeIt;
4.31 + typedef typename G::InEdgeIt InEdgeIt;
4.32 +
4.33 + typename G::EdgeMap<LpGlpk::Col> x(g);
4.34 + // lp.addColSet(x);
4.35 + for(EdgeIt e(g);e!=INVALID;++e) x[e]=lp.addCol();
4.36 +
4.37 + for(EdgeIt e(g);e!=INVALID;++e) {
4.38 + lp.setColUpperBound(x[e],cap[e]);
4.39 + lp.setColLowerBound(x[e],0);
4.40 + }
4.41 +
4.42 + for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) {
4.43 + LpGlpk::Expr ex;
4.44 + for(InEdgeIt e(g,n);e!=INVALID;++e) ex+=x[e];
4.45 + for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e];
4.46 + lp.addRow(0,ex,0);
4.47 + }
4.48 + {
4.49 + LpGlpk::Expr ex;
4.50 + for(InEdgeIt e(g,t);e!=INVALID;++e) ex+=x[e];
4.51 + for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e];
4.52 + lp.setObj(ex);
4.53 + }
4.54 +
4.55 + lp.solve();
4.56 +
4.57 + return 0;
4.58 +}
4.59 +
4.60 int main()
4.61 {
4.62 LpSolverSkeleton lp_skel;
4.63 @@ -46,4 +90,10 @@
4.64
4.65 lpTest(lp_skel);
4.66 lpTest(lp_glpk);
4.67 +
4.68 + ListGraph g;
4.69 + ListGraph::EdgeMap<double> cap(g);
4.70 +
4.71 + maxFlow(g,cap,ListGraph::NodeIt(g),ListGraph::NodeIt(g));
4.72 +
4.73 }