00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef LEMON_LP_BASE_H
00020 #define LEMON_LP_BASE_H
00021
00022 #include<vector>
00023 #include<map>
00024 #include<limits>
00025 #include<cmath>
00026
00027 #include<lemon/utility.h>
00028 #include<lemon/error.h>
00029 #include<lemon/invalid.h>
00030
00034 namespace lemon {
00035
00037
00039 class _FixId
00040 {
00041 protected:
00042 std::vector<int> index;
00043 std::vector<int> cross;
00044 int first_free;
00045 public:
00046 _FixId() : first_free(-1) {};
00048
00051 int fixId(int n) const {return cross[n];}
00053
00056 int floatingId(int n) const { return index[n];}
00058
00062 int insert(int n)
00063 {
00064 if(n>=int(cross.size())) {
00065 cross.resize(n+1);
00066 if(first_free==-1) {
00067 cross[n]=index.size();
00068 index.push_back(n);
00069 }
00070 else {
00071 cross[n]=first_free;
00072 int next=index[first_free];
00073 index[first_free]=n;
00074 first_free=next;
00075 }
00076 return cross[n];
00077 }
00079 else throw LogicError();
00080 }
00082
00085 void erase(int n)
00086 {
00087 int fl=index[n];
00088 index[n]=first_free;
00089 first_free=n;
00090 for(int i=fl+1;i<int(cross.size());++i) {
00091 cross[i-1]=cross[i];
00092 index[cross[i]]--;
00093 }
00094 cross.pop_back();
00095 }
00097
00100 std::size_t maxFixId() { return cross.size()-1; }
00101
00102 };
00103
00105
00108 class LpSolverBase {
00109
00110 public:
00111
00113 enum SolveExitStatus {
00117 SOLVED = 0,
00119 UNSOLVED = 1
00120 };
00121
00123 enum SolutionStatus {
00125
00128 UNDEFINED = 0,
00130 INFEASIBLE = 1,
00132 FEASIBLE = 2,
00134 OPTIMAL = 3,
00136
00139 INFINITE = 4
00140 };
00141
00143 enum ProblemTypes {
00145 PRIMAL_DUAL_FEASIBLE = 0,
00147 PRIMAL_FEASIBLE_DUAL_INFEASIBLE = 1,
00149 PRIMAL_INFEASIBLE_DUAL_FEASIBLE = 2,
00151 PRIMAL_DUAL_INFEASIBLE = 3,
00153 UNKNOWN = 4
00154 };
00155
00157 typedef double Value;
00159 static const Value INF;
00161 static const Value NaN;
00162
00164
00172 class Col {
00173 protected:
00174 int id;
00175 friend class LpSolverBase;
00176 public:
00177 typedef Value ExprValue;
00178 typedef True LpSolverCol;
00179 Col() {}
00180 Col(const Invalid&) : id(-1) {}
00181 bool operator< (Col c) const {return id< c.id;}
00182 bool operator> (Col c) const {return id> c.id;}
00183 bool operator==(Col c) const {return id==c.id;}
00184 bool operator!=(Col c) const {return id!=c.id;}
00185 };
00186
00188
00196 class Row {
00197 protected:
00198 int id;
00199 friend class LpSolverBase;
00200 public:
00201 typedef Value ExprValue;
00202 typedef True LpSolverRow;
00203 Row() {}
00204 Row(const Invalid&) : id(-1) {}
00205
00206 bool operator< (Row c) const {return id< c.id;}
00207 bool operator> (Row c) const {return id> c.id;}
00208 bool operator==(Row c) const {return id==c.id;}
00209 bool operator!=(Row c) const {return id!=c.id;}
00210 };
00211
00213
00262 class Expr : public std::map<Col,Value>
00263 {
00264 public:
00265 typedef LpSolverBase::Col Key;
00266 typedef LpSolverBase::Value Value;
00267
00268 protected:
00269 typedef std::map<Col,Value> Base;
00270
00271 Value const_comp;
00272 public:
00273 typedef True IsLinExpression;
00275 Expr() : Base(), const_comp(0) { }
00277 Expr(const Key &v) : const_comp(0) {
00278 Base::insert(std::make_pair(v, 1));
00279 }
00281 Expr(const Value &v) : const_comp(v) {}
00283 void set(const Key &v,const Value &c) {
00284 Base::insert(std::make_pair(v, c));
00285 }
00287 Value &constComp() { return const_comp; }
00289 const Value &constComp() const { return const_comp; }
00290
00292 void simplify() {
00293 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00294 Base::iterator j=i;
00295 ++j;
00296 if ((*i).second==0) Base::erase(i);
00297 j=i;
00298 }
00299 }
00300
00302 void simplify(double &tolerance) {
00303 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00304 Base::iterator j=i;
00305 ++j;
00306 if (std::fabs((*i).second)<tolerance) Base::erase(i);
00307 j=i;
00308 }
00309 }
00310
00312 void clear() {
00313 Base::clear();
00314 const_comp=0;
00315 }
00316
00318 Expr &operator+=(const Expr &e) {
00319 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00320 (*this)[j->first]+=j->second;
00321 const_comp+=e.const_comp;
00322 return *this;
00323 }
00325 Expr &operator-=(const Expr &e) {
00326 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00327 (*this)[j->first]-=j->second;
00328 const_comp-=e.const_comp;
00329 return *this;
00330 }
00332 Expr &operator*=(const Value &c) {
00333 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00334 j->second*=c;
00335 const_comp*=c;
00336 return *this;
00337 }
00339 Expr &operator/=(const Value &c) {
00340 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00341 j->second/=c;
00342 const_comp/=c;
00343 return *this;
00344 }
00345 };
00346
00348
00373 class Constr
00374 {
00375 public:
00376 typedef LpSolverBase::Expr Expr;
00377 typedef Expr::Key Key;
00378 typedef Expr::Value Value;
00379
00380
00381
00382
00383 protected:
00384 Expr _expr;
00385 Value _lb,_ub;
00386 public:
00388 Constr() : _expr(), _lb(NaN), _ub(NaN) {}
00390 Constr(Value lb,const Expr &e,Value ub) :
00391 _expr(e), _lb(lb), _ub(ub) {}
00393 Constr(const Expr &e,Value ub) :
00394 _expr(e), _lb(NaN), _ub(ub) {}
00396 Constr(Value lb,const Expr &e) :
00397 _expr(e), _lb(lb), _ub(NaN) {}
00399 Constr(const Expr &e) :
00400 _expr(e), _lb(NaN), _ub(NaN) {}
00402 void clear()
00403 {
00404 _expr.clear();
00405 _lb=_ub=NaN;
00406 }
00407
00409 Expr &expr() { return _expr; }
00411 const Expr &expr() const { return _expr; }
00413
00418 Value &lowerBound() { return _lb; }
00420 const Value &lowerBound() const { return _lb; }
00422
00427 Value &upperBound() { return _ub; }
00429 const Value &upperBound() const { return _ub; }
00431 bool lowerBounded() const {
00432 using namespace std;
00433 return finite(_lb);
00434 }
00436 bool upperBounded() const {
00437 using namespace std;
00438 return finite(_ub);
00439 }
00440 };
00441
00443
00486 class DualExpr : public std::map<Row,Value>
00487 {
00488 public:
00489 typedef LpSolverBase::Row Key;
00490 typedef LpSolverBase::Value Value;
00491
00492 protected:
00493 typedef std::map<Row,Value> Base;
00494
00495 public:
00496 typedef True IsLinExpression;
00498 DualExpr() : Base() { }
00500 DualExpr(const Key &v) {
00501 Base::insert(std::make_pair(v, 1));
00502 }
00504 void set(const Key &v,const Value &c) {
00505 Base::insert(std::make_pair(v, c));
00506 }
00507
00509 void simplify() {
00510 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00511 Base::iterator j=i;
00512 ++j;
00513 if ((*i).second==0) Base::erase(i);
00514 j=i;
00515 }
00516 }
00517
00519 void simplify(double &tolerance) {
00520 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00521 Base::iterator j=i;
00522 ++j;
00523 if (std::fabs((*i).second)<tolerance) Base::erase(i);
00524 j=i;
00525 }
00526 }
00527
00528
00530 void clear() {
00531 Base::clear();
00532 }
00533
00535 DualExpr &operator+=(const DualExpr &e) {
00536 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00537 (*this)[j->first]+=j->second;
00538 return *this;
00539 }
00541 DualExpr &operator-=(const DualExpr &e) {
00542 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00543 (*this)[j->first]-=j->second;
00544 return *this;
00545 }
00547 DualExpr &operator*=(const Value &c) {
00548 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00549 j->second*=c;
00550 return *this;
00551 }
00553 DualExpr &operator/=(const Value &c) {
00554 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00555 j->second/=c;
00556 return *this;
00557 }
00558 };
00559
00560
00561 protected:
00562 _FixId rows;
00563 _FixId cols;
00564
00565
00566 virtual LpSolverBase &_newLp() = 0;
00567 virtual LpSolverBase &_copyLp(){
00569
00570
00571 LpSolverBase & newlp(_newLp());
00572 return newlp;
00573
00574 };
00575
00576 virtual int _addCol() = 0;
00577 virtual int _addRow() = 0;
00578 virtual void _eraseCol(int col) = 0;
00579 virtual void _eraseRow(int row) = 0;
00580 virtual void _getColName(int col, std::string & name) = 0;
00581 virtual void _setColName(int col, const std::string & name) = 0;
00582 virtual void _setRowCoeffs(int i,
00583 int length,
00584 int const * indices,
00585 Value const * values ) = 0;
00586 virtual void _setColCoeffs(int i,
00587 int length,
00588 int const * indices,
00589 Value const * values ) = 0;
00590 virtual void _setCoeff(int row, int col, Value value) = 0;
00591 virtual void _setColLowerBound(int i, Value value) = 0;
00592 virtual void _setColUpperBound(int i, Value value) = 0;
00593
00594
00595 virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
00596 virtual void _setObjCoeff(int i, Value obj_coef) = 0;
00597 virtual void _clearObj()=0;
00598
00599
00600
00601 virtual SolveExitStatus _solve() = 0;
00602 virtual Value _getPrimal(int i) = 0;
00603 virtual Value _getDual(int i) = 0;
00604 virtual Value _getPrimalValue() = 0;
00605 virtual bool _isBasicCol(int i) = 0;
00606 virtual SolutionStatus _getPrimalStatus() = 0;
00607 virtual SolutionStatus _getDualStatus() = 0;
00610 virtual ProblemTypes _getProblemType() = 0;
00611
00612 virtual void _setMax() = 0;
00613 virtual void _setMin() = 0;
00614
00615
00616
00617
00618 Value obj_const_comp;
00619
00620
00621
00622
00623 public:
00624
00626 LpSolverBase() : obj_const_comp(0) {}
00627
00629 virtual ~LpSolverBase() {}
00630
00632 LpSolverBase &newLp() {return _newLp();}
00634 LpSolverBase ©Lp() {return _copyLp();}
00635
00637
00639
00641 Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
00642
00669 #ifdef DOXYGEN
00670 template<class T>
00671 int addColSet(T &t) { return 0;}
00672 #else
00673 template<class T>
00674 typename enable_if<typename T::value_type::LpSolverCol,int>::type
00675 addColSet(T &t,dummy<0> = 0) {
00676 int s=0;
00677 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
00678 return s;
00679 }
00680 template<class T>
00681 typename enable_if<typename T::value_type::second_type::LpSolverCol,
00682 int>::type
00683 addColSet(T &t,dummy<1> = 1) {
00684 int s=0;
00685 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00686 i->second=addCol();
00687 s++;
00688 }
00689 return s;
00690 }
00691 template<class T>
00692 typename enable_if<typename T::MapIt::Value::LpSolverCol,
00693 int>::type
00694 addColSet(T &t,dummy<2> = 2) {
00695 int s=0;
00696 for(typename T::MapIt i(t); i!=INVALID; ++i)
00697 {
00698 i.set(addCol());
00699 s++;
00700 }
00701 return s;
00702 }
00703 #endif
00704
00706
00710 void col(Col c,const DualExpr &e) {
00711 std::vector<int> indices;
00712 std::vector<Value> values;
00713 indices.push_back(0);
00714 values.push_back(0);
00715 for(DualExpr::const_iterator i=e.begin(); i!=e.end(); ++i)
00716 if((*i).second!=0) {
00717 indices.push_back(rows.floatingId((*i).first.id));
00718 values.push_back((*i).second);
00719 }
00720 _setColCoeffs(cols.floatingId(c.id),indices.size()-1,
00721 &indices[0],&values[0]);
00722 }
00723
00725
00730 Col addCol(const DualExpr &e, Value obj=0) {
00731 Col c=addCol();
00732 col(c,e);
00733 objCoeff(c,obj);
00734 return c;
00735 }
00736
00738
00741 Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
00742
00769 #ifdef DOXYGEN
00770 template<class T>
00771 int addRowSet(T &t) { return 0;}
00772 #else
00773 template<class T>
00774 typename enable_if<typename T::value_type::LpSolverRow,int>::type
00775 addRowSet(T &t,dummy<0> = 0) {
00776 int s=0;
00777 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
00778 return s;
00779 }
00780 template<class T>
00781 typename enable_if<typename T::value_type::second_type::LpSolverRow,
00782 int>::type
00783 addRowSet(T &t,dummy<1> = 1) {
00784 int s=0;
00785 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00786 i->second=addRow();
00787 s++;
00788 }
00789 return s;
00790 }
00791 template<class T>
00792 typename enable_if<typename T::MapIt::Value::LpSolverRow,
00793 int>::type
00794 addRowSet(T &t,dummy<2> = 2) {
00795 int s=0;
00796 for(typename T::MapIt i(t); i!=INVALID; ++i)
00797 {
00798 i.set(addRow());
00799 s++;
00800 }
00801 return s;
00802 }
00803 #endif
00804
00806
00815 void row(Row r, Value l,const Expr &e, Value u) {
00816 std::vector<int> indices;
00817 std::vector<Value> values;
00818 indices.push_back(0);
00819 values.push_back(0);
00820 for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
00821 if((*i).second!=0) {
00822 indices.push_back(cols.floatingId((*i).first.id));
00823 values.push_back((*i).second);
00824 }
00825 _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
00826 &indices[0],&values[0]);
00827
00828
00829 _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp());
00830 }
00831
00833
00836 void row(Row r, const Constr &c) {
00837 row(r,
00838 c.lowerBounded()?c.lowerBound():-INF,
00839 c.expr(),
00840 c.upperBounded()?c.upperBound():INF);
00841 }
00842
00844
00851 Row addRow(Value l,const Expr &e, Value u) {
00852 Row r=addRow();
00853 row(r,l,e,u);
00854 return r;
00855 }
00856
00858
00861 Row addRow(const Constr &c) {
00862 Row r=addRow();
00863 row(r,c);
00864 return r;
00865 }
00867
00870 void eraseCol(Col c) {
00871 _eraseCol(cols.floatingId(c.id));
00872 cols.erase(c.id);
00873 }
00875
00878 void eraseRow(Row r) {
00879 _eraseRow(rows.floatingId(r.id));
00880 rows.erase(r.id);
00881 }
00882
00884
00887 std::string ColName(Col c){
00888 std::string name;
00889 _getColName(cols.floatingId(c.id), name);
00890 return name;
00891 }
00892
00894
00897 void ColName(Col c, const std::string & name){
00898 _setColName(cols.floatingId(c.id), name);
00899 }
00900
00902
00906
00907 void Coeff(Row r, Col c, Value val){
00908 _setCoeff(rows.floatingId(r.id),cols.floatingId(c.id), val);
00909 }
00910
00912
00916 void colLowerBound(Col c, Value value) {
00917 _setColLowerBound(cols.floatingId(c.id),value);
00918 }
00919
00928 #ifdef DOXYGEN
00929 template<class T>
00930 void colLowerBound(T &t, Value value) { return 0;}
00931 #else
00932 template<class T>
00933 typename enable_if<typename T::value_type::LpSolverCol,void>::type
00934 colLowerBound(T &t, Value value,dummy<0> = 0) {
00935 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00936 colLowerBound(*i, value);
00937 }
00938 }
00939 template<class T>
00940 typename enable_if<typename T::value_type::second_type::LpSolverCol,
00941 void>::type
00942 colLowerBound(T &t, Value value,dummy<1> = 1) {
00943 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00944 colLowerBound(i->second, value);
00945 }
00946 }
00947 template<class T>
00948 typename enable_if<typename T::MapIt::Value::LpSolverCol,
00949 void>::type
00950 colLowerBound(T &t, Value value,dummy<2> = 2) {
00951 for(typename T::MapIt i(t); i!=INVALID; ++i){
00952 colLowerBound(*i, value);
00953 }
00954 }
00955 #endif
00956
00958
00962 void colUpperBound(Col c, Value value) {
00963 _setColUpperBound(cols.floatingId(c.id),value);
00964 };
00965
00974 #ifdef DOXYGEN
00975 template<class T>
00976 void colUpperBound(T &t, Value value) { return 0;}
00977 #else
00978 template<class T>
00979 typename enable_if<typename T::value_type::LpSolverCol,void>::type
00980 colUpperBound(T &t, Value value,dummy<0> = 0) {
00981 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00982 colUpperBound(*i, value);
00983 }
00984 }
00985 template<class T>
00986 typename enable_if<typename T::value_type::second_type::LpSolverCol,
00987 void>::type
00988 colUpperBound(T &t, Value value,dummy<1> = 1) {
00989 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00990 colUpperBound(i->second, value);
00991 }
00992 }
00993 template<class T>
00994 typename enable_if<typename T::MapIt::Value::LpSolverCol,
00995 void>::type
00996 colUpperBound(T &t, Value value,dummy<2> = 2) {
00997 for(typename T::MapIt i(t); i!=INVALID; ++i){
00998 colUpperBound(*i, value);
00999 }
01000 }
01001 #endif
01002
01004
01009 void colBounds(Col c, Value lower, Value upper) {
01010 _setColLowerBound(cols.floatingId(c.id),lower);
01011 _setColUpperBound(cols.floatingId(c.id),upper);
01012 }
01013
01023 #ifdef DOXYGEN
01024 template<class T>
01025 void colBounds(T &t, Value lower, Value upper) { return 0;}
01026 #else
01027 template<class T>
01028 typename enable_if<typename T::value_type::LpSolverCol,void>::type
01029 colBounds(T &t, Value lower, Value upper,dummy<0> = 0) {
01030 for(typename T::iterator i=t.begin();i!=t.end();++i) {
01031 colBounds(*i, lower, upper);
01032 }
01033 }
01034 template<class T>
01035 typename enable_if<typename T::value_type::second_type::LpSolverCol,
01036 void>::type
01037 colBounds(T &t, Value lower, Value upper,dummy<1> = 1) {
01038 for(typename T::iterator i=t.begin();i!=t.end();++i) {
01039 colBounds(i->second, lower, upper);
01040 }
01041 }
01042 template<class T>
01043 typename enable_if<typename T::MapIt::Value::LpSolverCol,
01044 void>::type
01045 colBounds(T &t, Value lower, Value upper,dummy<2> = 2) {
01046 for(typename T::MapIt i(t); i!=INVALID; ++i){
01047 colBounds(*i, lower, upper);
01048 }
01049 }
01050 #endif
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01070
01075 void rowBounds(Row c, Value lower, Value upper) {
01076 _setRowBounds(rows.floatingId(c.id),lower, upper);
01077
01078 }
01079
01081 void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
01083
01086 void setObj(Expr e) {
01087 _clearObj();
01088 for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
01089 objCoeff((*i).first,(*i).second);
01090 obj_const_comp=e.constComp();
01091 }
01092
01094 void max() { _setMax(); }
01096 void min() { _setMin(); }
01097
01098
01100
01101
01103
01105
01111 SolveExitStatus solve() { return _solve(); }
01112
01114
01116
01118
01120 SolutionStatus primalStatus() {
01121 return _getPrimalStatus();
01122 }
01123
01125 SolutionStatus dualStatus() {
01126 return _getDualStatus();
01127 }
01128
01130 ProblemTypes problemType() {
01131 return _getProblemType();
01132 }
01133
01135 Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
01136
01138 Value dual(Row r) { return _getDual(rows.floatingId(r.id)); }
01139
01141 bool isBasicCol(Col c) { return _isBasicCol(cols.floatingId(c.id)); }
01142
01144
01150 Value primalValue() { return _getPrimalValue()+obj_const_comp;}
01152
01153 };
01154
01156
01159 inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
01160 const LpSolverBase::Expr &b)
01161 {
01162 LpSolverBase::Expr tmp(a);
01163 tmp+=b;
01164 return tmp;
01165 }
01167
01170 inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
01171 const LpSolverBase::Expr &b)
01172 {
01173 LpSolverBase::Expr tmp(a);
01174 tmp-=b;
01175 return tmp;
01176 }
01178
01181 inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
01182 const LpSolverBase::Value &b)
01183 {
01184 LpSolverBase::Expr tmp(a);
01185 tmp*=b;
01186 return tmp;
01187 }
01188
01190
01193 inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
01194 const LpSolverBase::Expr &b)
01195 {
01196 LpSolverBase::Expr tmp(b);
01197 tmp*=a;
01198 return tmp;
01199 }
01201
01204 inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
01205 const LpSolverBase::Value &b)
01206 {
01207 LpSolverBase::Expr tmp(a);
01208 tmp/=b;
01209 return tmp;
01210 }
01211
01213
01216 inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
01217 const LpSolverBase::Expr &f)
01218 {
01219 return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
01220 }
01221
01223
01226 inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
01227 const LpSolverBase::Expr &f)
01228 {
01229 return LpSolverBase::Constr(e,f);
01230 }
01231
01233
01236 inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
01237 const LpSolverBase::Value &f)
01238 {
01239 return LpSolverBase::Constr(e,f);
01240 }
01241
01243
01246 inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
01247 const LpSolverBase::Expr &f)
01248 {
01249 return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
01250 }
01251
01252
01254
01257 inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
01258 const LpSolverBase::Expr &f)
01259 {
01260 return LpSolverBase::Constr(f,e);
01261 }
01262
01263
01265
01268 inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
01269 const LpSolverBase::Value &f)
01270 {
01271 return LpSolverBase::Constr(f,e);
01272 }
01273
01275
01278 inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
01279 const LpSolverBase::Expr &f)
01280 {
01281 return LpSolverBase::Constr(0,e-f,0);
01282 }
01283
01285
01288 inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
01289 const LpSolverBase::Constr&c)
01290 {
01291 LpSolverBase::Constr tmp(c);
01293 if(!isnan(tmp.lowerBound())) throw LogicError();
01294 else tmp.lowerBound()=n;
01295 return tmp;
01296 }
01298
01301 inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
01302 const LpSolverBase::Value &n)
01303 {
01304 LpSolverBase::Constr tmp(c);
01306 if(!isnan(tmp.upperBound())) throw LogicError();
01307 else tmp.upperBound()=n;
01308 return tmp;
01309 }
01310
01312
01315 inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
01316 const LpSolverBase::Constr&c)
01317 {
01318 LpSolverBase::Constr tmp(c);
01320 if(!isnan(tmp.upperBound())) throw LogicError();
01321 else tmp.upperBound()=n;
01322 return tmp;
01323 }
01325
01328 inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
01329 const LpSolverBase::Value &n)
01330 {
01331 LpSolverBase::Constr tmp(c);
01333 if(!isnan(tmp.lowerBound())) throw LogicError();
01334 else tmp.lowerBound()=n;
01335 return tmp;
01336 }
01337
01339
01342 inline LpSolverBase::DualExpr operator+(const LpSolverBase::DualExpr &a,
01343 const LpSolverBase::DualExpr &b)
01344 {
01345 LpSolverBase::DualExpr tmp(a);
01346 tmp+=b;
01347 return tmp;
01348 }
01350
01353 inline LpSolverBase::DualExpr operator-(const LpSolverBase::DualExpr &a,
01354 const LpSolverBase::DualExpr &b)
01355 {
01356 LpSolverBase::DualExpr tmp(a);
01357 tmp-=b;
01358 return tmp;
01359 }
01361
01364 inline LpSolverBase::DualExpr operator*(const LpSolverBase::DualExpr &a,
01365 const LpSolverBase::Value &b)
01366 {
01367 LpSolverBase::DualExpr tmp(a);
01368 tmp*=b;
01369 return tmp;
01370 }
01371
01373
01376 inline LpSolverBase::DualExpr operator*(const LpSolverBase::Value &a,
01377 const LpSolverBase::DualExpr &b)
01378 {
01379 LpSolverBase::DualExpr tmp(b);
01380 tmp*=a;
01381 return tmp;
01382 }
01384
01387 inline LpSolverBase::DualExpr operator/(const LpSolverBase::DualExpr &a,
01388 const LpSolverBase::Value &b)
01389 {
01390 LpSolverBase::DualExpr tmp(a);
01391 tmp/=b;
01392 return tmp;
01393 }
01394
01395
01396 }
01397
01398 #endif //LEMON_LP_BASE_H