00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef LEMON_LP_BASE_H
00018 #define LEMON_LP_BASE_H
00019
00020 #include<vector>
00021 #include<map>
00022 #include<limits>
00023 #include<cmath>
00024
00025 #include<lemon/utility.h>
00026 #include<lemon/error.h>
00027 #include<lemon/invalid.h>
00028
00032 namespace lemon {
00033
00035
00037 class _FixId
00038 {
00039 std::vector<int> index;
00040 std::vector<int> cross;
00041 int first_free;
00042 public:
00043 _FixId() : first_free(-1) {};
00045
00048 int fixId(int n) const {return cross[n];}
00050
00053 int floatingId(int n) const { return index[n];}
00055
00059 int insert(int n)
00060 {
00061 if(n>=int(cross.size())) {
00062 cross.resize(n+1);
00063 if(first_free==-1) {
00064 cross[n]=index.size();
00065 index.push_back(n);
00066 }
00067 else {
00068 cross[n]=first_free;
00069 int next=index[first_free];
00070 index[first_free]=n;
00071 first_free=next;
00072 }
00073 return cross[n];
00074 }
00076 else throw LogicError();
00077 }
00079
00082 void erase(int n)
00083 {
00084 int fl=index[n];
00085 index[n]=first_free;
00086 first_free=n;
00087 for(int i=fl+1;i<int(cross.size());++i) {
00088 cross[i-1]=cross[i];
00089 index[cross[i]]--;
00090 }
00091 cross.pop_back();
00092 }
00094
00097 std::size_t maxFixId() { return cross.size()-1; }
00098
00099 };
00100
00102
00105 class LpSolverBase {
00106
00107 public:
00108
00110 enum SolveExitStatus {
00114 SOLVED = 0,
00116 UNSOLVED = 1
00117 };
00118
00120 enum SolutionStatus {
00122
00125 UNDEFINED = 0,
00127 INFEASIBLE = 1,
00129 FEASIBLE = 2,
00131 OPTIMAL = 3,
00133
00136 INFINITE = 4
00137 };
00138
00140 enum ProblemTypes {
00142 PRIMAL_DUAL_FEASIBLE = 0,
00144 PRIMAL_FEASIBLE_DUAL_INFEASIBLE = 1,
00146 PRIMAL_INFEASIBLE_DUAL_FEASIBLE = 2,
00148 PRIMAL_DUAL_INFEASIBLE = 3,
00150 UNKNOWN = 4
00151 };
00152
00154 typedef double Value;
00156 static const Value INF;
00158 static const Value NaN;
00159
00161
00169 class Col {
00170 protected:
00171 int id;
00172 friend class LpSolverBase;
00173 public:
00174 typedef Value ExprValue;
00175 typedef True LpSolverCol;
00176 Col() {}
00177 Col(const Invalid&) : id(-1) {}
00178 bool operator<(Col c) const {return id<c.id;}
00179 bool operator==(Col c) const {return id==c.id;}
00180 bool operator!=(Col c) const {return id==c.id;}
00181 };
00182
00184
00192 class Row {
00193 protected:
00194 int id;
00195 friend class LpSolverBase;
00196 public:
00197 typedef Value ExprValue;
00198 typedef True LpSolverRow;
00199 Row() {}
00200 Row(const Invalid&) : id(-1) {}
00201
00202 bool operator<(Row c) const {return id<c.id;}
00203 bool operator==(Row c) const {return id==c.id;}
00204 bool operator!=(Row c) const {return id==c.id;}
00205 };
00206
00208
00257 class Expr : public std::map<Col,Value>
00258 {
00259 public:
00260 typedef LpSolverBase::Col Key;
00261 typedef LpSolverBase::Value Value;
00262
00263 protected:
00264 typedef std::map<Col,Value> Base;
00265
00266 Value const_comp;
00267 public:
00268 typedef True IsLinExpression;
00270 Expr() : Base(), const_comp(0) { }
00272 Expr(const Key &v) : const_comp(0) {
00273 Base::insert(std::make_pair(v, 1));
00274 }
00276 Expr(const Value &v) : const_comp(v) {}
00278 void set(const Key &v,const Value &c) {
00279 Base::insert(std::make_pair(v, c));
00280 }
00282 Value &constComp() { return const_comp; }
00284 const Value &constComp() const { return const_comp; }
00285
00287 void simplify() {
00288 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00289 Base::iterator j=i;
00290 ++j;
00291 if ((*i).second==0) Base::erase(i);
00292 j=i;
00293 }
00294 }
00295
00297 void clear() {
00298 Base::clear();
00299 const_comp=0;
00300 }
00301
00303 Expr &operator+=(const Expr &e) {
00304 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00305 (*this)[j->first]+=j->second;
00307 const_comp+=e.const_comp;
00308 return *this;
00309 }
00311 Expr &operator-=(const Expr &e) {
00312 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00313 (*this)[j->first]-=j->second;
00314 const_comp-=e.const_comp;
00315 return *this;
00316 }
00318 Expr &operator*=(const Value &c) {
00319 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00320 j->second*=c;
00321 const_comp*=c;
00322 return *this;
00323 }
00325 Expr &operator/=(const Value &c) {
00326 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00327 j->second/=c;
00328 const_comp/=c;
00329 return *this;
00330 }
00331 };
00332
00334
00358 class Constr
00359 {
00360 public:
00361 typedef LpSolverBase::Expr Expr;
00362 typedef Expr::Key Key;
00363 typedef Expr::Value Value;
00364
00365
00366
00367
00368 protected:
00369 Expr _expr;
00370 Value _lb,_ub;
00371 public:
00373 Constr() : _expr(), _lb(NaN), _ub(NaN) {}
00375 Constr(Value lb,const Expr &e,Value ub) :
00376 _expr(e), _lb(lb), _ub(ub) {}
00378 Constr(const Expr &e,Value ub) :
00379 _expr(e), _lb(NaN), _ub(ub) {}
00381 Constr(Value lb,const Expr &e) :
00382 _expr(e), _lb(lb), _ub(NaN) {}
00384 Constr(const Expr &e) :
00385 _expr(e), _lb(NaN), _ub(NaN) {}
00387 void clear()
00388 {
00389 _expr.clear();
00390 _lb=_ub=NaN;
00391 }
00392
00394 Expr &expr() { return _expr; }
00396 const Expr &expr() const { return _expr; }
00398
00403 Value &lowerBound() { return _lb; }
00405 const Value &lowerBound() const { return _lb; }
00407
00412 Value &upperBound() { return _ub; }
00414 const Value &upperBound() const { return _ub; }
00416 bool lowerBounded() const {
00417 using namespace std;
00418 return finite(_lb);
00419 }
00421 bool upperBounded() const {
00422 using namespace std;
00423 return finite(_ub);
00424 }
00425 };
00426
00428
00471 class DualExpr : public std::map<Row,Value>
00472 {
00473 public:
00474 typedef LpSolverBase::Row Key;
00475 typedef LpSolverBase::Value Value;
00476
00477 protected:
00478 typedef std::map<Row,Value> Base;
00479
00480 public:
00481 typedef True IsLinExpression;
00483 DualExpr() : Base() { }
00485 DualExpr(const Key &v) {
00486 Base::insert(std::make_pair(v, 1));
00487 }
00489 void set(const Key &v,const Value &c) {
00490 Base::insert(std::make_pair(v, c));
00491 }
00492
00494 void simplify() {
00495 for (Base::iterator i=Base::begin(); i!=Base::end();) {
00496 Base::iterator j=i;
00497 ++j;
00498 if ((*i).second==0) Base::erase(i);
00499 j=i;
00500 }
00501 }
00502
00504 void clear() {
00505 Base::clear();
00506 }
00507
00509 DualExpr &operator+=(const DualExpr &e) {
00510 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00511 (*this)[j->first]+=j->second;
00513 return *this;
00514 }
00516 DualExpr &operator-=(const DualExpr &e) {
00517 for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
00518 (*this)[j->first]-=j->second;
00519 return *this;
00520 }
00522 DualExpr &operator*=(const Value &c) {
00523 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00524 j->second*=c;
00525 return *this;
00526 }
00528 DualExpr &operator/=(const Value &c) {
00529 for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
00530 j->second/=c;
00531 return *this;
00532 }
00533 };
00534
00535
00536 protected:
00537 _FixId rows;
00538 _FixId cols;
00539
00540
00541 virtual LpSolverBase &_newLp() = 0;
00542 virtual LpSolverBase &_copyLp(){
00544
00545
00546 LpSolverBase & newlp(_newLp());
00547 return newlp;
00548
00549 };
00550
00551 virtual int _addCol() = 0;
00552 virtual int _addRow() = 0;
00553 virtual void _eraseCol(int col) = 0;
00554 virtual void _eraseRow(int row) = 0;
00555 virtual void _setRowCoeffs(int i,
00556 int length,
00557 int const * indices,
00558 Value const * values ) = 0;
00559 virtual void _setColCoeffs(int i,
00560 int length,
00561 int const * indices,
00562 Value const * values ) = 0;
00563 virtual void _setCoeff(int row, int col, Value value) = 0;
00564 virtual void _setColLowerBound(int i, Value value) = 0;
00565 virtual void _setColUpperBound(int i, Value value) = 0;
00566
00567
00568 virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
00569 virtual void _setObjCoeff(int i, Value obj_coef) = 0;
00570 virtual void _clearObj()=0;
00571
00572
00573
00574 virtual SolveExitStatus _solve() = 0;
00575 virtual Value _getPrimal(int i) = 0;
00576 virtual Value _getPrimalValue() = 0;
00577 virtual SolutionStatus _getPrimalStatus() = 0;
00578 virtual SolutionStatus _getDualStatus() = 0;
00581 virtual ProblemTypes _getProblemType() = 0;
00582
00583 virtual void _setMax() = 0;
00584 virtual void _setMin() = 0;
00585
00586
00587
00588
00589 Value obj_const_comp;
00590
00591
00592
00593
00594 public:
00595
00597 LpSolverBase() : obj_const_comp(0) {}
00598
00600 virtual ~LpSolverBase() {}
00601
00603 LpSolverBase &newLp() {return _newLp();}
00605 LpSolverBase ©Lp() {return _copyLp();}
00606
00608
00610
00612 Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
00613
00640 #ifdef DOXYGEN
00641 template<class T>
00642 int addColSet(T &t) { return 0;}
00643 #else
00644 template<class T>
00645 typename enable_if<typename T::value_type::LpSolverCol,int>::type
00646 addColSet(T &t,dummy<0> = 0) {
00647 int s=0;
00648 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
00649 return s;
00650 }
00651 template<class T>
00652 typename enable_if<typename T::value_type::second_type::LpSolverCol,
00653 int>::type
00654 addColSet(T &t,dummy<1> = 1) {
00655 int s=0;
00656 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00657 i->second=addCol();
00658 s++;
00659 }
00660 return s;
00661 }
00662 template<class T>
00663 typename enable_if<typename T::ValueSet::value_type::LpSolverCol,
00664 int>::type
00665 addColSet(T &t,dummy<2> = 2) {
00667 int s=0;
00668 for(typename T::ValueSet::iterator i=t.valueSet().begin();
00669 i!=t.valueSet().end();
00670 ++i)
00671 {
00672 *i=addCol();
00673 s++;
00674 }
00675 return s;
00676 }
00677 #endif
00678
00680
00685 void setCol(Col c,const DualExpr &e) {
00686 std::vector<int> indices;
00687 std::vector<Value> values;
00688 indices.push_back(0);
00689 values.push_back(0);
00690 for(DualExpr::const_iterator i=e.begin(); i!=e.end(); ++i)
00691 if((*i).second!=0) {
00692 indices.push_back(cols.floatingId((*i).first.id));
00693 values.push_back((*i).second);
00694 }
00695 _setColCoeffs(cols.floatingId(c.id),indices.size()-1,
00696 &indices[0],&values[0]);
00697 }
00698
00700
00707 Col addCol(const DualExpr &e, Value obj=0) {
00708 Col c=addCol();
00709 setCol(c,e);
00710 objCoeff(c,obj);
00711 return c;
00712 }
00713
00715
00718 Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
00719
00746 #ifdef DOXYGEN
00747 template<class T>
00748 int addRowSet(T &t) { return 0;}
00749 #else
00750 template<class T>
00751 typename enable_if<typename T::value_type::LpSolverRow,int>::type
00752 addRowSet(T &t,dummy<0> = 0) {
00753 int s=0;
00754 for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
00755 return s;
00756 }
00757 template<class T>
00758 typename enable_if<typename T::value_type::second_type::LpSolverRow,
00759 int>::type
00760 addRowSet(T &t,dummy<1> = 1) {
00761 int s=0;
00762 for(typename T::iterator i=t.begin();i!=t.end();++i) {
00763 i->second=addRow();
00764 s++;
00765 }
00766 return s;
00767 }
00768 template<class T>
00769 typename enable_if<typename T::ValueSet::value_type::LpSolverRow,
00770 int>::type
00771 addRowSet(T &t,dummy<2> = 2) {
00773 int s=0;
00774 for(typename T::ValueSet::iterator i=t.valueSet().begin();
00775 i!=t.valueSet().end();
00776 ++i)
00777 {
00778 *i=addRow();
00779 s++;
00780 }
00781 return s;
00782 }
00783 #endif
00784
00786
00795 void setRow(Row r, Value l,const Expr &e, Value u) {
00796 std::vector<int> indices;
00797 std::vector<Value> values;
00798 indices.push_back(0);
00799 values.push_back(0);
00800 for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
00801 if((*i).second!=0) {
00802 indices.push_back(cols.floatingId((*i).first.id));
00803 values.push_back((*i).second);
00804 }
00805 _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
00806 &indices[0],&values[0]);
00807
00808
00809 _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp());
00810 }
00811
00813
00816 void setRow(Row r, const Constr &c) {
00817 setRow(r,
00818 c.lowerBounded()?c.lowerBound():-INF,
00819 c.expr(),
00820 c.upperBounded()?c.upperBound():INF);
00821 }
00822
00824
00831 Row addRow(Value l,const Expr &e, Value u) {
00832 Row r=addRow();
00833 setRow(r,l,e,u);
00834 return r;
00835 }
00836
00838
00841 Row addRow(const Constr &c) {
00842 Row r=addRow();
00843 setRow(r,c);
00844 return r;
00845 }
00847
00850 void eraseCol(Col c) {
00851 _eraseCol(cols.floatingId(c.id));
00852 cols.erase(c.id);
00853 }
00855
00858 void eraseRow(Row r) {
00859 _eraseRow(rows.floatingId(r.id));
00860 rows.erase(r.id);
00861 }
00862
00864
00868 void setCoeff(Row r, Col c, Value val){
00869 _setCoeff(rows.floatingId(r.id),cols.floatingId(c.id), val);
00870 }
00871
00873
00877 void colLowerBound(Col c, Value value) {
00878 _setColLowerBound(cols.floatingId(c.id),value);
00879 }
00881
00885 void colUpperBound(Col c, Value value) {
00886 _setColUpperBound(cols.floatingId(c.id),value);
00887 };
00889
00894 void colBounds(Col c, Value lower, Value upper) {
00895 _setColLowerBound(cols.floatingId(c.id),lower);
00896 _setColUpperBound(cols.floatingId(c.id),upper);
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00917
00922 void rowBounds(Row c, Value lower, Value upper) {
00923 _setRowBounds(rows.floatingId(c.id),lower, upper);
00924
00925 }
00926
00928 void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
00930
00933 void setObj(Expr e) {
00934 _clearObj();
00935 for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
00936 objCoeff((*i).first,(*i).second);
00937 obj_const_comp=e.constComp();
00938 }
00939
00941 void max() { _setMax(); }
00943 void min() { _setMin(); }
00944
00945
00947
00948
00950
00952
00958 SolveExitStatus solve() { return _solve(); }
00959
00961
00963
00965
00967 SolutionStatus primalStatus() {
00968 return _getPrimalStatus();
00969 }
00970
00972 SolutionStatus dualStatus() {
00973 return _getDualStatus();
00974 }
00975
00977 ProblemTypes problemType() {
00978 return _getProblemType();
00979 }
00980
00982 Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
00983
00985
00991 Value primalValue() { return _getPrimalValue()+obj_const_comp;}
00993
00994 };
00995
00997
01000 inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
01001 const LpSolverBase::Expr &b)
01002 {
01003 LpSolverBase::Expr tmp(a);
01004 tmp+=b;
01005 return tmp;
01006 }
01008
01011 inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
01012 const LpSolverBase::Expr &b)
01013 {
01014 LpSolverBase::Expr tmp(a);
01015 tmp-=b;
01016 return tmp;
01017 }
01019
01022 inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
01023 const LpSolverBase::Value &b)
01024 {
01025 LpSolverBase::Expr tmp(a);
01026 tmp*=b;
01027 return tmp;
01028 }
01029
01031
01034 inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
01035 const LpSolverBase::Expr &b)
01036 {
01037 LpSolverBase::Expr tmp(b);
01038 tmp*=a;
01039 return tmp;
01040 }
01042
01045 inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
01046 const LpSolverBase::Value &b)
01047 {
01048 LpSolverBase::Expr tmp(a);
01049 tmp/=b;
01050 return tmp;
01051 }
01052
01054
01057 inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
01058 const LpSolverBase::Expr &f)
01059 {
01060 return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
01061 }
01062
01064
01067 inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
01068 const LpSolverBase::Expr &f)
01069 {
01070 return LpSolverBase::Constr(e,f);
01071 }
01072
01074
01077 inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
01078 const LpSolverBase::Value &f)
01079 {
01080 return LpSolverBase::Constr(e,f);
01081 }
01082
01084
01087 inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
01088 const LpSolverBase::Expr &f)
01089 {
01090 return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
01091 }
01092
01093
01095
01098 inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
01099 const LpSolverBase::Expr &f)
01100 {
01101 return LpSolverBase::Constr(f,e);
01102 }
01103
01104
01106
01109 inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
01110 const LpSolverBase::Value &f)
01111 {
01112 return LpSolverBase::Constr(f,e);
01113 }
01114
01116
01119 inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
01120 const LpSolverBase::Expr &f)
01121 {
01122 return LpSolverBase::Constr(0,e-f,0);
01123 }
01124
01126
01129 inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
01130 const LpSolverBase::Constr&c)
01131 {
01132 LpSolverBase::Constr tmp(c);
01134 if(!isnan(tmp.lowerBound())) throw LogicError();
01135 else tmp.lowerBound()=n;
01136 return tmp;
01137 }
01139
01142 inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
01143 const LpSolverBase::Value &n)
01144 {
01145 LpSolverBase::Constr tmp(c);
01147 if(!isnan(tmp.upperBound())) throw LogicError();
01148 else tmp.upperBound()=n;
01149 return tmp;
01150 }
01151
01153
01156 inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
01157 const LpSolverBase::Constr&c)
01158 {
01159 LpSolverBase::Constr tmp(c);
01161 if(!isnan(tmp.upperBound())) throw LogicError();
01162 else tmp.upperBound()=n;
01163 return tmp;
01164 }
01166
01169 inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
01170 const LpSolverBase::Value &n)
01171 {
01172 LpSolverBase::Constr tmp(c);
01174 if(!isnan(tmp.lowerBound())) throw LogicError();
01175 else tmp.lowerBound()=n;
01176 return tmp;
01177 }
01178
01180
01183 inline LpSolverBase::DualExpr operator+(const LpSolverBase::DualExpr &a,
01184 const LpSolverBase::DualExpr &b)
01185 {
01186 LpSolverBase::DualExpr tmp(a);
01187 tmp+=b;
01188 return tmp;
01189 }
01191
01194 inline LpSolverBase::DualExpr operator-(const LpSolverBase::DualExpr &a,
01195 const LpSolverBase::DualExpr &b)
01196 {
01197 LpSolverBase::DualExpr tmp(a);
01198 tmp-=b;
01199 return tmp;
01200 }
01202
01205 inline LpSolverBase::DualExpr operator*(const LpSolverBase::DualExpr &a,
01206 const LpSolverBase::Value &b)
01207 {
01208 LpSolverBase::DualExpr tmp(a);
01209 tmp*=b;
01210 return tmp;
01211 }
01212
01214
01217 inline LpSolverBase::DualExpr operator*(const LpSolverBase::Value &a,
01218 const LpSolverBase::DualExpr &b)
01219 {
01220 LpSolverBase::DualExpr tmp(b);
01221 tmp*=a;
01222 return tmp;
01223 }
01225
01228 inline LpSolverBase::DualExpr operator/(const LpSolverBase::DualExpr &a,
01229 const LpSolverBase::Value &b)
01230 {
01231 LpSolverBase::DualExpr tmp(a);
01232 tmp/=b;
01233 return tmp;
01234 }
01235
01236
01237 }
01238
01239 #endif //LEMON_LP_BASE_H