# HG changeset patch
# User Balazs Dezso <deba@inf.elte.hu>
# Date 1228485765 -3600
# Node ID 9347462c31067ff85c7691347bb28585967daf09
# Parent f259f5b9d9c7ebd5f31318849759c73af275f82f
Lp improvments (ticket #44)
- Add macro CLP macro definition to config.h.in
- Update lp.h to use soplex and clp
- Remove default_solver_name
- New solverName() function in solvers
- Fix the objective value retrieval in CLP
- Rename basic classes
- SolverBase -> LpBase
- LpBase -> LpSolver
- MipBase -> MipSolver
- Handle exceptions for MipCplex test
- Rename tolerance parameter to epsilon
- Rename MapIt to CoeffIt
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/config.h.in
|
a
|
b
|
|
| 5 | 5 | #undef HAVE_GLPK |
| 6 | 6 | |
| 7 | 7 | /* Define to 1 if you have SOPLEX */ |
| 8 | | #undef HAVE_SOPLEX |
| 9 | | No newline at end of file |
| | 8 | #undef HAVE_SOPLEX |
| | 9 | |
| | 10 | /* Define to 1 if you have CLP */ |
| | 11 | #undef HAVE_CLP |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp.h
|
a
|
b
|
|
| 28 | 28 | #include <lemon/lp_cplex.h> |
| 29 | 29 | #elif HAVE_SOPLEX |
| 30 | 30 | #include <lemon/lp_soplex.h> |
| | 31 | #elif HAVE_CLP |
| | 32 | #include <lemon/lp_clp.h> |
| 31 | 33 | #endif |
| 32 | 34 | |
| 33 | 35 | ///\file |
| … |
… |
|
| 41 | 43 | ///The default LP solver identifier. |
| 42 | 44 | ///\ingroup lp_group |
| 43 | 45 | /// |
| 44 | | ///Currently, the possible values are \c GLPK or \c CPLEX |
| 45 | | #define DEFAULT_LP SOLVER |
| | 46 | ///Currently, the possible values are \c LP_GLPK, \c LP_CPLEX, \c |
| | 47 | ///LP_SOPLEX or \c LP_CLP |
| | 48 | #define LEMON_DEFAULT_LP SOLVER |
| 46 | 49 | ///The default LP solver |
| 47 | 50 | |
| 48 | 51 | ///The default LP solver. |
| 49 | 52 | ///\ingroup lp_group |
| 50 | 53 | /// |
| 51 | | ///Currently, it is either \c LpGlpk or \c LpCplex |
| | 54 | ///Currently, it is either \c LpGlpk, \c LpCplex, \c LpSoplex or \c LpClp |
| 52 | 55 | typedef LpGlpk Lp; |
| 53 | | ///The default LP solver identifier string |
| 54 | 56 | |
| 55 | | ///The default LP solver identifier string. |
| | 57 | ///The default MIP solver identifier |
| | 58 | |
| | 59 | ///The default MIP solver identifier. |
| 56 | 60 | ///\ingroup lp_group |
| 57 | 61 | /// |
| 58 | | ///Currently, the possible values are "GLPK" or "CPLEX" |
| 59 | | const char default_solver_name[]="SOLVER"; |
| | 62 | ///Currently, the possible values are \c MIP_GLPK or \c MIP_CPLEX |
| | 63 | #define LEMON_DEFAULT_MIP SOLVER |
| | 64 | ///The default MIP solver. |
| 60 | 65 | |
| 61 | | ///The default ILP solver. |
| 62 | | |
| 63 | | ///The default ILP solver. |
| | 66 | ///The default MIP solver. |
| 64 | 67 | ///\ingroup lp_group |
| 65 | 68 | /// |
| 66 | | ///Currently, it is either \c LpGlpk or \c LpCplex |
| | 69 | ///Currently, it is either \c MipGlpk or \c MipCplex |
| 67 | 70 | typedef MipGlpk Mip; |
| 68 | 71 | #else |
| 69 | 72 | #ifdef HAVE_GLPK |
| 70 | | #define DEFAULT_LP GLPK |
| | 73 | # define LEMON_DEFAULT_LP LP_GLPK |
| 71 | 74 | typedef LpGlpk Lp; |
| | 75 | # define LEMON_DEFAULT_MIP MIP_GLPK |
| 72 | 76 | typedef MipGlpk Mip; |
| 73 | | const char default_solver_name[]="GLPK"; |
| 74 | 77 | #elif HAVE_CPLEX |
| 75 | | #define DEFAULT_LP CPLEX |
| | 78 | # define LEMON_DEFAULT_LP LP_CPLEX |
| 76 | 79 | typedef LpCplex Lp; |
| | 80 | # define LEMON_DEFAULT_MIP MIP_CPLEX |
| 77 | 81 | typedef MipCplex Mip; |
| 78 | | const char default_solver_name[]="CPLEX"; |
| 79 | 82 | #elif HAVE_SOPLEX |
| 80 | | #define DEFAULT_LP SOPLEX |
| | 83 | # define DEFAULT_LP LP_SOPLEX |
| 81 | 84 | typedef LpSoplex Lp; |
| 82 | | const char default_solver_name[]="SOPLEX"; |
| | 85 | #elif HAVE_CLP |
| | 86 | # define DEFAULT_LP LP_CLP |
| | 87 | typedef LpClp Lp; |
| 83 | 88 | #endif |
| 84 | 89 | #endif |
| 85 | 90 | |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_base.cc
|
a
|
b
|
|
| 22 | 22 | #include <lemon/lp_base.h> |
| 23 | 23 | namespace lemon { |
| 24 | 24 | |
| 25 | | const LpBase::Value |
| 26 | | SolverBase::INF = std::numeric_limits<Value>::infinity(); |
| 27 | | const LpBase::Value |
| 28 | | SolverBase::NaN = std::numeric_limits<Value>::quiet_NaN(); |
| 29 | | |
| 30 | | // const LpBase::Constr::Value |
| 31 | | // LpBase::Constr::INF = std::numeric_limits<Value>::infinity(); |
| 32 | | // const LpBase::Constr::Value |
| 33 | | // LpBase::Constr::NaN = std::numeric_limits<Value>::quiet_NaN(); |
| | 25 | const LpBase::Value LpBase::INF = std::numeric_limits<Value>::infinity(); |
| | 26 | const LpBase::Value LpBase::NaN = std::numeric_limits<Value>::quiet_NaN(); |
| 34 | 27 | |
| 35 | 28 | } //namespace lemon |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_base.h
|
a
|
b
|
|
| 36 | 36 | ///\ingroup lp_group |
| 37 | 37 | namespace lemon { |
| 38 | 38 | |
| 39 | | ///Common base class for LP solvers |
| | 39 | ///Common base class for LP and MIP solvers |
| 40 | 40 | |
| 41 | 41 | ///\todo Much more docs |
| 42 | 42 | ///\ingroup lp_group |
| 43 | | class SolverBase { |
| | 43 | class LpBase { |
| 44 | 44 | |
| 45 | 45 | protected: |
| 46 | 46 | |
| … |
… |
|
| 90 | 90 | ///\todo Document what can one do with a Col (INVALID, comparing, |
| 91 | 91 | ///it is similar to Node/Edge) |
| 92 | 92 | class Col { |
| 93 | | friend class SolverBase; |
| | 93 | friend class LpBase; |
| 94 | 94 | protected: |
| 95 | 95 | int _id; |
| 96 | 96 | explicit Col(int id) : _id(id) {} |
| … |
… |
|
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | 107 | class ColIt : public Col { |
| 108 | | const SolverBase *_solver; |
| | 108 | const LpBase *_solver; |
| 109 | 109 | public: |
| 110 | 110 | ColIt() {} |
| 111 | | ColIt(const SolverBase &solver) : _solver(&solver) |
| | 111 | ColIt(const LpBase &solver) : _solver(&solver) |
| 112 | 112 | { |
| 113 | 113 | _solver->cols.firstItem(_id); |
| 114 | 114 | } |
| … |
… |
|
| 133 | 133 | ///\todo Document what can one do with a Row (INVALID, comparing, |
| 134 | 134 | ///it is similar to Node/Edge) |
| 135 | 135 | class Row { |
| 136 | | friend class SolverBase; |
| | 136 | friend class LpBase; |
| 137 | 137 | protected: |
| 138 | 138 | int _id; |
| 139 | 139 | explicit Row(int id) : _id(id) {} |
| … |
… |
|
| 149 | 149 | }; |
| 150 | 150 | |
| 151 | 151 | class RowIt : public Row { |
| 152 | | const SolverBase *_solver; |
| | 152 | const LpBase *_solver; |
| 153 | 153 | public: |
| 154 | 154 | RowIt() {} |
| 155 | | RowIt(const SolverBase &solver) : _solver(&solver) |
| | 155 | RowIt(const LpBase &solver) : _solver(&solver) |
| 156 | 156 | { |
| 157 | 157 | _solver->rows.firstItem(_id); |
| 158 | 158 | } |
| … |
… |
|
| 184 | 184 | ///or you can also iterate through its elements. |
| 185 | 185 | ///\code |
| 186 | 186 | ///double s=0; |
| 187 | | ///for(SolverBase::Expr::ConstMapIt i(e);i!=INVALID;++i) |
| | 187 | ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i) |
| 188 | 188 | /// s+=*i * primal(i); |
| 189 | 189 | ///\endcode |
| 190 | 190 | ///(This code computes the primal value of the expression). |
| … |
… |
|
| 216 | 216 | ///\sa Constr |
| 217 | 217 | /// |
| 218 | 218 | class Expr { |
| 219 | | friend class SolverBase; |
| | 219 | friend class LpBase; |
| 220 | 220 | public: |
| 221 | | typedef SolverBase::Col Key; |
| 222 | | typedef SolverBase::Value Value; |
| | 221 | typedef LpBase::Col Key; |
| | 222 | typedef LpBase::Value Value; |
| 223 | 223 | |
| 224 | 224 | protected: |
| 225 | 225 | Value const_comp; |
| … |
… |
|
| 264 | 264 | ///\e |
| 265 | 265 | const Value& operator*() const { return const_comp; } |
| 266 | 266 | |
| 267 | | ///Removes the coefficients closer to zero than \c tolerance. |
| 268 | | void simplify(Value tolerance = 0.0) { |
| | 267 | ///Removes the coefficients closer to zero than \c epsilon. |
| | 268 | void simplify(Value epsilon = 0.0) { |
| 269 | 269 | std::map<int, Value>::iterator it=comps.begin(); |
| 270 | 270 | while (it != comps.end()) { |
| 271 | 271 | std::map<int, Value>::iterator jt=it; |
| 272 | 272 | ++jt; |
| 273 | | if (std::fabs((*it).second) <= tolerance) comps.erase(it); |
| | 273 | if (std::fabs((*it).second) <= epsilon) comps.erase(it); |
| 274 | 274 | it=jt; |
| 275 | 275 | } |
| 276 | | if (std::fabs(const_comp) <= tolerance) const_comp = 0; |
| | 276 | if (std::fabs(const_comp) <= epsilon) const_comp = 0; |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | | void simplify(Value tolerance = 0.0) const { |
| 280 | | const_cast<Expr*>(this)->simplify(tolerance); |
| | 279 | void simplify(Value epsilon = 0.0) const { |
| | 280 | const_cast<Expr*>(this)->simplify(epsilon); |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | ///Sets all coefficients and the constant component to 0. |
| … |
… |
|
| 319 | 319 | return *this; |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | | class MapIt { |
| | 322 | class CoeffIt { |
| 323 | 323 | private: |
| 324 | 324 | |
| 325 | 325 | std::map<int, Value>::iterator _it, _end; |
| 326 | 326 | |
| 327 | 327 | public: |
| 328 | 328 | |
| 329 | | MapIt(Expr& e) |
| | 329 | CoeffIt(Expr& e) |
| 330 | 330 | : _it(e.comps.begin()), _end(e.comps.end()){} |
| 331 | 331 | |
| 332 | 332 | operator Col() const { |
| … |
… |
|
| 336 | 336 | Value& operator*() { return _it->second; } |
| 337 | 337 | const Value& operator*() const { return _it->second; } |
| 338 | 338 | |
| 339 | | MapIt& operator++() { ++_it; return *this; } |
| | 339 | CoeffIt& operator++() { ++_it; return *this; } |
| 340 | 340 | |
| 341 | 341 | bool operator==(Invalid) const { return _it == _end; } |
| 342 | 342 | bool operator!=(Invalid) const { return _it != _end; } |
| 343 | 343 | }; |
| 344 | 344 | |
| 345 | | class ConstMapIt { |
| | 345 | class ConstCoeffIt { |
| 346 | 346 | private: |
| 347 | 347 | |
| 348 | 348 | std::map<int, Value>::const_iterator _it, _end; |
| 349 | 349 | |
| 350 | 350 | public: |
| 351 | 351 | |
| 352 | | ConstMapIt(const Expr& e) |
| | 352 | ConstCoeffIt(const Expr& e) |
| 353 | 353 | : _it(e.comps.begin()), _end(e.comps.end()){} |
| 354 | 354 | |
| 355 | 355 | operator Col() const { |
| … |
… |
|
| 358 | 358 | |
| 359 | 359 | const Value& operator*() const { return _it->second; } |
| 360 | 360 | |
| 361 | | ConstMapIt& operator++() { ++_it; return *this; } |
| | 361 | ConstCoeffIt& operator++() { ++_it; return *this; } |
| 362 | 362 | |
| 363 | 363 | bool operator==(Invalid) const { return _it == _end; } |
| 364 | 364 | bool operator!=(Invalid) const { return _it != _end; } |
| … |
… |
|
| 395 | 395 | class Constr |
| 396 | 396 | { |
| 397 | 397 | public: |
| 398 | | typedef SolverBase::Expr Expr; |
| | 398 | typedef LpBase::Expr Expr; |
| 399 | 399 | typedef Expr::Key Key; |
| 400 | 400 | typedef Expr::Value Value; |
| 401 | 401 | |
| … |
… |
|
| 406 | 406 | ///\e |
| 407 | 407 | Constr() : _expr(), _lb(NaN), _ub(NaN) {} |
| 408 | 408 | ///\e |
| 409 | | Constr(Value lb,const Expr &e,Value ub) : |
| | 409 | Constr(Value lb, const Expr &e, Value ub) : |
| 410 | 410 | _expr(e), _lb(lb), _ub(ub) {} |
| 411 | 411 | Constr(const Expr &e) : |
| 412 | 412 | _expr(e), _lb(NaN), _ub(NaN) {} |
| … |
… |
|
| 466 | 466 | ///or you can also iterate through its elements. |
| 467 | 467 | ///\code |
| 468 | 468 | ///double s=0; |
| 469 | | ///for(SolverBase::DualExpr::ConstMapIt i(e);i!=INVALID;++i) |
| | 469 | ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i) |
| 470 | 470 | /// s+=*i; |
| 471 | 471 | ///\endcode |
| 472 | 472 | ///(This code computes the sum of all coefficients). |
| … |
… |
|
| 490 | 490 | ///\sa Expr |
| 491 | 491 | /// |
| 492 | 492 | class DualExpr { |
| 493 | | friend class SolverBase; |
| | 493 | friend class LpBase; |
| 494 | 494 | public: |
| 495 | | typedef SolverBase::Row Key; |
| 496 | | typedef SolverBase::Value Value; |
| | 495 | typedef LpBase::Row Key; |
| | 496 | typedef LpBase::Value Value; |
| 497 | 497 | |
| 498 | 498 | protected: |
| 499 | 499 | std::map<int, Value> comps; |
| … |
… |
|
| 530 | 530 | } |
| 531 | 531 | } |
| 532 | 532 | |
| 533 | | ///Removes the coefficients closer to zero than \c tolerance. |
| 534 | | void simplify(Value tolerance = 0.0) { |
| | 533 | ///Removes the coefficients closer to zero than \c epsilon. |
| | 534 | void simplify(Value epsilon = 0.0) { |
| 535 | 535 | std::map<int, Value>::iterator it=comps.begin(); |
| 536 | 536 | while (it != comps.end()) { |
| 537 | 537 | std::map<int, Value>::iterator jt=it; |
| 538 | 538 | ++jt; |
| 539 | | if (std::fabs((*it).second) <= tolerance) comps.erase(it); |
| | 539 | if (std::fabs((*it).second) <= epsilon) comps.erase(it); |
| 540 | 540 | it=jt; |
| 541 | 541 | } |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | | void simplify(Value tolerance = 0.0) const { |
| 545 | | const_cast<DualExpr*>(this)->simplify(tolerance); |
| | 544 | void simplify(Value epsilon = 0.0) const { |
| | 545 | const_cast<DualExpr*>(this)->simplify(epsilon); |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | 548 | ///Sets all coefficients to 0. |
| … |
… |
|
| 579 | 579 | return *this; |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | | class MapIt { |
| | 582 | class CoeffIt { |
| 583 | 583 | private: |
| 584 | 584 | |
| 585 | 585 | std::map<int, Value>::iterator _it, _end; |
| 586 | 586 | |
| 587 | 587 | public: |
| 588 | 588 | |
| 589 | | MapIt(DualExpr& e) |
| | 589 | CoeffIt(DualExpr& e) |
| 590 | 590 | : _it(e.comps.begin()), _end(e.comps.end()){} |
| 591 | 591 | |
| 592 | 592 | operator Row() const { |
| … |
… |
|
| 596 | 596 | Value& operator*() { return _it->second; } |
| 597 | 597 | const Value& operator*() const { return _it->second; } |
| 598 | 598 | |
| 599 | | MapIt& operator++() { ++_it; return *this; } |
| | 599 | CoeffIt& operator++() { ++_it; return *this; } |
| 600 | 600 | |
| 601 | 601 | bool operator==(Invalid) const { return _it == _end; } |
| 602 | 602 | bool operator!=(Invalid) const { return _it != _end; } |
| 603 | 603 | }; |
| 604 | 604 | |
| 605 | | class ConstMapIt { |
| | 605 | class ConstCoeffIt { |
| 606 | 606 | private: |
| 607 | 607 | |
| 608 | 608 | std::map<int, Value>::const_iterator _it, _end; |
| 609 | 609 | |
| 610 | 610 | public: |
| 611 | 611 | |
| 612 | | ConstMapIt(const DualExpr& e) |
| | 612 | ConstCoeffIt(const DualExpr& e) |
| 613 | 613 | : _it(e.comps.begin()), _end(e.comps.end()){} |
| 614 | 614 | |
| 615 | 615 | operator Row() const { |
| … |
… |
|
| 618 | 618 | |
| 619 | 619 | const Value& operator*() const { return _it->second; } |
| 620 | 620 | |
| 621 | | ConstMapIt& operator++() { ++_it; return *this; } |
| | 621 | ConstCoeffIt& operator++() { ++_it; return *this; } |
| 622 | 622 | |
| 623 | 623 | bool operator==(Invalid) const { return _it == _end; } |
| 624 | 624 | bool operator!=(Invalid) const { return _it != _end; } |
| … |
… |
|
| 712 | 712 | protected: |
| 713 | 713 | |
| 714 | 714 | //Abstract virtual functions |
| 715 | | virtual SolverBase* _newSolver() const = 0; |
| 716 | | virtual SolverBase* _cloneSolver() const = 0; |
| | 715 | virtual LpBase* _newSolver() const = 0; |
| | 716 | virtual LpBase* _cloneSolver() const = 0; |
| 717 | 717 | |
| 718 | 718 | virtual int _addColId(int col) { return cols.addIndex(col); } |
| 719 | 719 | virtual int _addRowId(int row) { return rows.addIndex(row); } |
| … |
… |
|
| 767 | 767 | |
| 768 | 768 | virtual void _clear() = 0; |
| 769 | 769 | |
| | 770 | virtual const char* _solverName() const = 0; |
| | 771 | |
| 770 | 772 | //Own protected stuff |
| 771 | 773 | |
| 772 | 774 | //Constant component of the objective function |
| … |
… |
|
| 775 | 777 | public: |
| 776 | 778 | |
| 777 | 779 | ///\e |
| 778 | | SolverBase() : rows(), cols(), obj_const_comp(0) { |
| | 780 | LpBase() : rows(), cols(), obj_const_comp(0) { |
| 779 | 781 | } |
| 780 | 782 | |
| 781 | 783 | ///\e |
| 782 | | virtual ~SolverBase() {} |
| | 784 | virtual ~LpBase() {} |
| 783 | 785 | |
| 784 | 786 | ///Creates a new LP problem |
| 785 | | SolverBase* newSolver() {return _newSolver();} |
| | 787 | LpBase* newSolver() {return _newSolver();} |
| 786 | 788 | ///Makes a copy of the LP problem |
| 787 | | SolverBase* cloneSolver() {return _cloneSolver();} |
| | 789 | LpBase* cloneSolver() {return _cloneSolver();} |
| | 790 | |
| | 791 | ///Gives back the name of the solver. |
| | 792 | const char* solverName() const {return _solverName();} |
| 788 | 793 | |
| 789 | 794 | ///\name Build up and modify the LP |
| 790 | 795 | |
| … |
… |
|
| 804 | 809 | ///\ref Col as its \c values_type |
| 805 | 810 | ///like |
| 806 | 811 | ///\code |
| 807 | | ///std::vector<SolverBase::Col> |
| 808 | | ///std::list<SolverBase::Col> |
| | 812 | ///std::vector<LpBase::Col> |
| | 813 | ///std::list<LpBase::Col> |
| 809 | 814 | ///\endcode |
| 810 | 815 | ///- a standard STL compatible iterable container with |
| 811 | 816 | ///\ref Col as its \c mapped_type |
| 812 | 817 | ///like |
| 813 | 818 | ///\code |
| 814 | | ///std::map<AnyType,SolverBase::Col> |
| | 819 | ///std::map<AnyType,LpBase::Col> |
| 815 | 820 | ///\endcode |
| 816 | 821 | ///- an iterable lemon \ref concepts::WriteMap "write map" like |
| 817 | 822 | ///\code |
| 818 | | ///ListGraph::NodeMap<SolverBase::Col> |
| 819 | | ///ListGraph::ArcMap<SolverBase::Col> |
| | 823 | ///ListGraph::NodeMap<LpBase::Col> |
| | 824 | ///ListGraph::ArcMap<LpBase::Col> |
| 820 | 825 | ///\endcode |
| 821 | 826 | ///\return The number of the created column. |
| 822 | 827 | #ifdef DOXYGEN |
| … |
… |
|
| 906 | 911 | ///\ref Row as its \c values_type |
| 907 | 912 | ///like |
| 908 | 913 | ///\code |
| 909 | | ///std::vector<SolverBase::Row> |
| 910 | | ///std::list<SolverBase::Row> |
| | 914 | ///std::vector<LpBase::Row> |
| | 915 | ///std::list<LpBase::Row> |
| 911 | 916 | ///\endcode |
| 912 | 917 | ///- a standard STL compatible iterable container with |
| 913 | 918 | ///\ref Row as its \c mapped_type |
| 914 | 919 | ///like |
| 915 | 920 | ///\code |
| 916 | | ///std::map<AnyType,SolverBase::Row> |
| | 921 | ///std::map<AnyType,LpBase::Row> |
| 917 | 922 | ///\endcode |
| 918 | 923 | ///- an iterable lemon \ref concepts::WriteMap "write map" like |
| 919 | 924 | ///\code |
| 920 | | ///ListGraph::NodeMap<SolverBase::Row> |
| 921 | | ///ListGraph::ArcMap<SolverBase::Row> |
| | 925 | ///ListGraph::NodeMap<LpBase::Row> |
| | 926 | ///ListGraph::ArcMap<LpBase::Row> |
| 922 | 927 | ///\endcode |
| 923 | 928 | ///\return The number of rows created. |
| 924 | 929 | #ifdef DOXYGEN |
| … |
… |
|
| 1341 | 1346 | |
| 1342 | 1347 | }; |
| 1343 | 1348 | |
| 1344 | | ///\relates SolverBase::Expr |
| | 1349 | ///\relates LpBase::Expr |
| 1345 | 1350 | /// |
| 1346 | | inline SolverBase::Expr operator+(const SolverBase::Expr &a, |
| 1347 | | const SolverBase::Expr &b) { |
| 1348 | | SolverBase::Expr tmp(a); |
| | 1351 | inline LpBase::Expr operator+(const LpBase::Expr &a, |
| | 1352 | const LpBase::Expr &b) { |
| | 1353 | LpBase::Expr tmp(a); |
| 1349 | 1354 | tmp+=b; |
| 1350 | 1355 | return tmp; |
| 1351 | 1356 | } |
| 1352 | 1357 | ///\e |
| 1353 | 1358 | |
| 1354 | | ///\relates SolverBase::Expr |
| | 1359 | ///\relates LpBase::Expr |
| 1355 | 1360 | /// |
| 1356 | | inline SolverBase::Expr operator-(const SolverBase::Expr &a, |
| 1357 | | const SolverBase::Expr &b) { |
| 1358 | | SolverBase::Expr tmp(a); |
| | 1361 | inline LpBase::Expr operator-(const LpBase::Expr &a, |
| | 1362 | const LpBase::Expr &b) { |
| | 1363 | LpBase::Expr tmp(a); |
| 1359 | 1364 | tmp-=b; |
| 1360 | 1365 | return tmp; |
| 1361 | 1366 | } |
| 1362 | 1367 | ///\e |
| 1363 | 1368 | |
| 1364 | | ///\relates SolverBase::Expr |
| | 1369 | ///\relates LpBase::Expr |
| 1365 | 1370 | /// |
| 1366 | | inline SolverBase::Expr operator*(const SolverBase::Expr &a, |
| 1367 | | const SolverBase::Value &b) { |
| 1368 | | SolverBase::Expr tmp(a); |
| | 1371 | inline LpBase::Expr operator*(const LpBase::Expr &a, |
| | 1372 | const LpBase::Value &b) { |
| | 1373 | LpBase::Expr tmp(a); |
| 1369 | 1374 | tmp*=b; |
| 1370 | 1375 | return tmp; |
| 1371 | 1376 | } |
| 1372 | 1377 | |
| 1373 | 1378 | ///\e |
| 1374 | 1379 | |
| 1375 | | ///\relates SolverBase::Expr |
| | 1380 | ///\relates LpBase::Expr |
| 1376 | 1381 | /// |
| 1377 | | inline SolverBase::Expr operator*(const SolverBase::Value &a, |
| 1378 | | const SolverBase::Expr &b) { |
| 1379 | | SolverBase::Expr tmp(b); |
| | 1382 | inline LpBase::Expr operator*(const LpBase::Value &a, |
| | 1383 | const LpBase::Expr &b) { |
| | 1384 | LpBase::Expr tmp(b); |
| 1380 | 1385 | tmp*=a; |
| 1381 | 1386 | return tmp; |
| 1382 | 1387 | } |
| 1383 | 1388 | ///\e |
| 1384 | 1389 | |
| 1385 | | ///\relates SolverBase::Expr |
| | 1390 | ///\relates LpBase::Expr |
| 1386 | 1391 | /// |
| 1387 | | inline SolverBase::Expr operator/(const SolverBase::Expr &a, |
| 1388 | | const SolverBase::Value &b) { |
| 1389 | | SolverBase::Expr tmp(a); |
| | 1392 | inline LpBase::Expr operator/(const LpBase::Expr &a, |
| | 1393 | const LpBase::Value &b) { |
| | 1394 | LpBase::Expr tmp(a); |
| 1390 | 1395 | tmp/=b; |
| 1391 | 1396 | return tmp; |
| 1392 | 1397 | } |
| 1393 | 1398 | |
| 1394 | 1399 | ///\e |
| 1395 | 1400 | |
| 1396 | | ///\relates SolverBase::Constr |
| | 1401 | ///\relates LpBase::Constr |
| 1397 | 1402 | /// |
| 1398 | | inline SolverBase::Constr operator<=(const SolverBase::Expr &e, |
| 1399 | | const SolverBase::Expr &f) { |
| 1400 | | return SolverBase::Constr(0, f - e, SolverBase::INF); |
| | 1403 | inline LpBase::Constr operator<=(const LpBase::Expr &e, |
| | 1404 | const LpBase::Expr &f) { |
| | 1405 | return LpBase::Constr(0, f - e, LpBase::INF); |
| 1401 | 1406 | } |
| 1402 | 1407 | |
| 1403 | 1408 | ///\e |
| 1404 | 1409 | |
| 1405 | | ///\relates SolverBase::Constr |
| | 1410 | ///\relates LpBase::Constr |
| 1406 | 1411 | /// |
| 1407 | | inline SolverBase::Constr operator<=(const SolverBase::Value &e, |
| 1408 | | const SolverBase::Expr &f) { |
| 1409 | | return SolverBase::Constr(e, f, SolverBase::NaN); |
| | 1412 | inline LpBase::Constr operator<=(const LpBase::Value &e, |
| | 1413 | const LpBase::Expr &f) { |
| | 1414 | return LpBase::Constr(e, f, LpBase::NaN); |
| 1410 | 1415 | } |
| 1411 | 1416 | |
| 1412 | 1417 | ///\e |
| 1413 | 1418 | |
| 1414 | | ///\relates SolverBase::Constr |
| | 1419 | ///\relates LpBase::Constr |
| 1415 | 1420 | /// |
| 1416 | | inline SolverBase::Constr operator<=(const SolverBase::Expr &e, |
| 1417 | | const SolverBase::Value &f) { |
| 1418 | | return SolverBase::Constr(- SolverBase::INF, e, f); |
| | 1421 | inline LpBase::Constr operator<=(const LpBase::Expr &e, |
| | 1422 | const LpBase::Value &f) { |
| | 1423 | return LpBase::Constr(- LpBase::INF, e, f); |
| 1419 | 1424 | } |
| 1420 | 1425 | |
| 1421 | 1426 | ///\e |
| 1422 | 1427 | |
| 1423 | | ///\relates SolverBase::Constr |
| | 1428 | ///\relates LpBase::Constr |
| 1424 | 1429 | /// |
| 1425 | | inline SolverBase::Constr operator>=(const SolverBase::Expr &e, |
| 1426 | | const SolverBase::Expr &f) { |
| 1427 | | return SolverBase::Constr(0, e - f, SolverBase::INF); |
| | 1430 | inline LpBase::Constr operator>=(const LpBase::Expr &e, |
| | 1431 | const LpBase::Expr &f) { |
| | 1432 | return LpBase::Constr(0, e - f, LpBase::INF); |
| 1428 | 1433 | } |
| 1429 | 1434 | |
| 1430 | 1435 | |
| 1431 | 1436 | ///\e |
| 1432 | 1437 | |
| 1433 | | ///\relates SolverBase::Constr |
| | 1438 | ///\relates LpBase::Constr |
| 1434 | 1439 | /// |
| 1435 | | inline SolverBase::Constr operator>=(const SolverBase::Value &e, |
| 1436 | | const SolverBase::Expr &f) { |
| 1437 | | return SolverBase::Constr(SolverBase::NaN, f, e); |
| | 1440 | inline LpBase::Constr operator>=(const LpBase::Value &e, |
| | 1441 | const LpBase::Expr &f) { |
| | 1442 | return LpBase::Constr(LpBase::NaN, f, e); |
| 1438 | 1443 | } |
| 1439 | 1444 | |
| 1440 | 1445 | |
| 1441 | 1446 | ///\e |
| 1442 | 1447 | |
| 1443 | | ///\relates SolverBase::Constr |
| | 1448 | ///\relates LpBase::Constr |
| 1444 | 1449 | /// |
| 1445 | | inline SolverBase::Constr operator>=(const SolverBase::Expr &e, |
| 1446 | | const SolverBase::Value &f) { |
| 1447 | | return SolverBase::Constr(f, e, SolverBase::INF); |
| | 1450 | inline LpBase::Constr operator>=(const LpBase::Expr &e, |
| | 1451 | const LpBase::Value &f) { |
| | 1452 | return LpBase::Constr(f, e, LpBase::INF); |
| 1448 | 1453 | } |
| 1449 | 1454 | |
| 1450 | 1455 | ///\e |
| 1451 | 1456 | |
| 1452 | | ///\relates SolverBase::Constr |
| | 1457 | ///\relates LpBase::Constr |
| 1453 | 1458 | /// |
| 1454 | | inline SolverBase::Constr operator==(const SolverBase::Expr &e, |
| 1455 | | const SolverBase::Value &f) { |
| 1456 | | return SolverBase::Constr(f, e, f); |
| | 1459 | inline LpBase::Constr operator==(const LpBase::Expr &e, |
| | 1460 | const LpBase::Value &f) { |
| | 1461 | return LpBase::Constr(f, e, f); |
| 1457 | 1462 | } |
| 1458 | 1463 | |
| 1459 | 1464 | ///\e |
| 1460 | 1465 | |
| 1461 | | ///\relates SolverBase::Constr |
| | 1466 | ///\relates LpBase::Constr |
| 1462 | 1467 | /// |
| 1463 | | inline SolverBase::Constr operator==(const SolverBase::Expr &e, |
| 1464 | | const SolverBase::Expr &f) { |
| 1465 | | return SolverBase::Constr(0, f - e, 0); |
| | 1468 | inline LpBase::Constr operator==(const LpBase::Expr &e, |
| | 1469 | const LpBase::Expr &f) { |
| | 1470 | return LpBase::Constr(0, f - e, 0); |
| 1466 | 1471 | } |
| 1467 | 1472 | |
| 1468 | 1473 | ///\e |
| 1469 | 1474 | |
| 1470 | | ///\relates SolverBase::Constr |
| | 1475 | ///\relates LpBase::Constr |
| 1471 | 1476 | /// |
| 1472 | | inline SolverBase::Constr operator<=(const SolverBase::Value &n, |
| 1473 | | const SolverBase::Constr &c) { |
| 1474 | | SolverBase::Constr tmp(c); |
| | 1477 | inline LpBase::Constr operator<=(const LpBase::Value &n, |
| | 1478 | const LpBase::Constr &c) { |
| | 1479 | LpBase::Constr tmp(c); |
| 1475 | 1480 | LEMON_ASSERT(std::isnan(tmp.lowerBound()), "Wrong LP constraint"); |
| 1476 | 1481 | tmp.lowerBound()=n; |
| 1477 | 1482 | return tmp; |
| 1478 | 1483 | } |
| 1479 | 1484 | ///\e |
| 1480 | 1485 | |
| 1481 | | ///\relates SolverBase::Constr |
| | 1486 | ///\relates LpBase::Constr |
| 1482 | 1487 | /// |
| 1483 | | inline SolverBase::Constr operator<=(const SolverBase::Constr &c, |
| 1484 | | const SolverBase::Value &n) |
| | 1488 | inline LpBase::Constr operator<=(const LpBase::Constr &c, |
| | 1489 | const LpBase::Value &n) |
| 1485 | 1490 | { |
| 1486 | | SolverBase::Constr tmp(c); |
| | 1491 | LpBase::Constr tmp(c); |
| 1487 | 1492 | LEMON_ASSERT(std::isnan(tmp.upperBound()), "Wrong LP constraint"); |
| 1488 | 1493 | tmp.upperBound()=n; |
| 1489 | 1494 | return tmp; |
| … |
… |
|
| 1491 | 1496 | |
| 1492 | 1497 | ///\e |
| 1493 | 1498 | |
| 1494 | | ///\relates SolverBase::Constr |
| | 1499 | ///\relates LpBase::Constr |
| 1495 | 1500 | /// |
| 1496 | | inline SolverBase::Constr operator>=(const SolverBase::Value &n, |
| 1497 | | const SolverBase::Constr &c) { |
| 1498 | | SolverBase::Constr tmp(c); |
| | 1501 | inline LpBase::Constr operator>=(const LpBase::Value &n, |
| | 1502 | const LpBase::Constr &c) { |
| | 1503 | LpBase::Constr tmp(c); |
| 1499 | 1504 | LEMON_ASSERT(std::isnan(tmp.upperBound()), "Wrong LP constraint"); |
| 1500 | 1505 | tmp.upperBound()=n; |
| 1501 | 1506 | return tmp; |
| 1502 | 1507 | } |
| 1503 | 1508 | ///\e |
| 1504 | 1509 | |
| 1505 | | ///\relates SolverBase::Constr |
| | 1510 | ///\relates LpBase::Constr |
| 1506 | 1511 | /// |
| 1507 | | inline SolverBase::Constr operator>=(const SolverBase::Constr &c, |
| 1508 | | const SolverBase::Value &n) |
| | 1512 | inline LpBase::Constr operator>=(const LpBase::Constr &c, |
| | 1513 | const LpBase::Value &n) |
| 1509 | 1514 | { |
| 1510 | | SolverBase::Constr tmp(c); |
| | 1515 | LpBase::Constr tmp(c); |
| 1511 | 1516 | LEMON_ASSERT(std::isnan(tmp.lowerBound()), "Wrong LP constraint"); |
| 1512 | 1517 | tmp.lowerBound()=n; |
| 1513 | 1518 | return tmp; |
| … |
… |
|
| 1515 | 1520 | |
| 1516 | 1521 | ///\e |
| 1517 | 1522 | |
| 1518 | | ///\relates SolverBase::DualExpr |
| | 1523 | ///\relates LpBase::DualExpr |
| 1519 | 1524 | /// |
| 1520 | | inline SolverBase::DualExpr operator+(const SolverBase::DualExpr &a, |
| 1521 | | const SolverBase::DualExpr &b) { |
| 1522 | | SolverBase::DualExpr tmp(a); |
| | 1525 | inline LpBase::DualExpr operator+(const LpBase::DualExpr &a, |
| | 1526 | const LpBase::DualExpr &b) { |
| | 1527 | LpBase::DualExpr tmp(a); |
| 1523 | 1528 | tmp+=b; |
| 1524 | 1529 | return tmp; |
| 1525 | 1530 | } |
| 1526 | 1531 | ///\e |
| 1527 | 1532 | |
| 1528 | | ///\relates SolverBase::DualExpr |
| | 1533 | ///\relates LpBase::DualExpr |
| 1529 | 1534 | /// |
| 1530 | | inline SolverBase::DualExpr operator-(const SolverBase::DualExpr &a, |
| 1531 | | const SolverBase::DualExpr &b) { |
| 1532 | | SolverBase::DualExpr tmp(a); |
| | 1535 | inline LpBase::DualExpr operator-(const LpBase::DualExpr &a, |
| | 1536 | const LpBase::DualExpr &b) { |
| | 1537 | LpBase::DualExpr tmp(a); |
| 1533 | 1538 | tmp-=b; |
| 1534 | 1539 | return tmp; |
| 1535 | 1540 | } |
| 1536 | 1541 | ///\e |
| 1537 | 1542 | |
| 1538 | | ///\relates SolverBase::DualExpr |
| | 1543 | ///\relates LpBase::DualExpr |
| 1539 | 1544 | /// |
| 1540 | | inline SolverBase::DualExpr operator*(const SolverBase::DualExpr &a, |
| 1541 | | const SolverBase::Value &b) { |
| 1542 | | SolverBase::DualExpr tmp(a); |
| | 1545 | inline LpBase::DualExpr operator*(const LpBase::DualExpr &a, |
| | 1546 | const LpBase::Value &b) { |
| | 1547 | LpBase::DualExpr tmp(a); |
| 1543 | 1548 | tmp*=b; |
| 1544 | 1549 | return tmp; |
| 1545 | 1550 | } |
| 1546 | 1551 | |
| 1547 | 1552 | ///\e |
| 1548 | 1553 | |
| 1549 | | ///\relates SolverBase::DualExpr |
| | 1554 | ///\relates LpBase::DualExpr |
| 1550 | 1555 | /// |
| 1551 | | inline SolverBase::DualExpr operator*(const SolverBase::Value &a, |
| 1552 | | const SolverBase::DualExpr &b) { |
| 1553 | | SolverBase::DualExpr tmp(b); |
| | 1556 | inline LpBase::DualExpr operator*(const LpBase::Value &a, |
| | 1557 | const LpBase::DualExpr &b) { |
| | 1558 | LpBase::DualExpr tmp(b); |
| 1554 | 1559 | tmp*=a; |
| 1555 | 1560 | return tmp; |
| 1556 | 1561 | } |
| 1557 | 1562 | ///\e |
| 1558 | 1563 | |
| 1559 | | ///\relates SolverBase::DualExpr |
| | 1564 | ///\relates LpBase::DualExpr |
| 1560 | 1565 | /// |
| 1561 | | inline SolverBase::DualExpr operator/(const SolverBase::DualExpr &a, |
| 1562 | | const SolverBase::Value &b) { |
| 1563 | | SolverBase::DualExpr tmp(a); |
| | 1566 | inline LpBase::DualExpr operator/(const LpBase::DualExpr &a, |
| | 1567 | const LpBase::Value &b) { |
| | 1568 | LpBase::DualExpr tmp(a); |
| 1564 | 1569 | tmp/=b; |
| 1565 | 1570 | return tmp; |
| 1566 | 1571 | } |
| … |
… |
|
| 1569 | 1574 | /// |
| 1570 | 1575 | /// \brief Common base class for LP solvers |
| 1571 | 1576 | /// \todo Much more docs |
| 1572 | | class LpBase : virtual public SolverBase { |
| | 1577 | class LpSolver : virtual public LpBase { |
| 1573 | 1578 | public: |
| 1574 | 1579 | |
| 1575 | 1580 | ///\e |
| … |
… |
|
| 1586 | 1591 | UNBOUNDED = 4 |
| 1587 | 1592 | }; |
| 1588 | 1593 | |
| | 1594 | ///\e |
| 1589 | 1595 | enum VarStatus { |
| 1590 | | BASIC, FREE, LOWER, UPPER, FIXED |
| | 1596 | /// The variable is in the basis |
| | 1597 | BASIC, |
| | 1598 | /// The variable is free, but not basic |
| | 1599 | FREE, |
| | 1600 | /// The variable has active lower bound |
| | 1601 | LOWER, |
| | 1602 | /// The variable has active upper bound |
| | 1603 | UPPER, |
| | 1604 | /// The variable is non-basic and fixed |
| | 1605 | FIXED |
| 1591 | 1606 | }; |
| 1592 | 1607 | |
| 1593 | 1608 | protected: |
| … |
… |
|
| 1644 | 1659 | ///\e |
| 1645 | 1660 | Value primal(const Expr& e) const { |
| 1646 | 1661 | double res = *e; |
| 1647 | | for (Expr::ConstMapIt c(e); c != INVALID; ++c) { |
| | 1662 | for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) { |
| 1648 | 1663 | res += *c * primal(c); |
| 1649 | 1664 | } |
| 1650 | 1665 | return res; |
| … |
… |
|
| 1657 | 1672 | ///\e |
| 1658 | 1673 | Value dual(const DualExpr& e) const { |
| 1659 | 1674 | double res = 0.0; |
| 1660 | | for (DualExpr::ConstMapIt r(e); r != INVALID; ++r) { |
| | 1675 | for (DualExpr::ConstCoeffIt r(e); r != INVALID; ++r) { |
| 1661 | 1676 | res += *r * dual(r); |
| 1662 | 1677 | } |
| 1663 | 1678 | return res; |
| … |
… |
|
| 1681 | 1696 | Value primal() const { return _getPrimalValue()+obj_const_comp;} |
| 1682 | 1697 | ///@} |
| 1683 | 1698 | |
| 1684 | | LpBase* newSolver() {return _newSolver();} |
| 1685 | | LpBase* cloneSolver() {return _cloneSolver();} |
| | 1699 | LpSolver* newSolver() {return _newSolver();} |
| | 1700 | LpSolver* cloneSolver() {return _cloneSolver();} |
| 1686 | 1701 | |
| 1687 | 1702 | protected: |
| 1688 | 1703 | |
| 1689 | | virtual LpBase* _newSolver() const = 0; |
| 1690 | | virtual LpBase* _cloneSolver() const = 0; |
| | 1704 | virtual LpSolver* _newSolver() const = 0; |
| | 1705 | virtual LpSolver* _cloneSolver() const = 0; |
| 1691 | 1706 | }; |
| 1692 | 1707 | |
| 1693 | 1708 | |
| … |
… |
|
| 1695 | 1710 | /// |
| 1696 | 1711 | /// \brief Common base class for MIP solvers |
| 1697 | 1712 | /// \todo Much more docs |
| 1698 | | class MipBase : virtual public SolverBase { |
| | 1713 | class MipSolver : virtual public LpBase { |
| 1699 | 1714 | public: |
| 1700 | 1715 | |
| 1701 | 1716 | ///\e |
| … |
… |
|
| 1799 | 1814 | ///\e |
| 1800 | 1815 | Value sol(const Expr& e) const { |
| 1801 | 1816 | double res = *e; |
| 1802 | | for (Expr::ConstMapIt c(e); c != INVALID; ++c) { |
| | 1817 | for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) { |
| 1803 | 1818 | res += *c * sol(c); |
| 1804 | 1819 | } |
| 1805 | 1820 | return res; |
| … |
… |
|
| 1823 | 1838 | |
| 1824 | 1839 | public: |
| 1825 | 1840 | |
| 1826 | | MipBase* newSolver() {return _newSolver();} |
| 1827 | | MipBase* cloneSolver() {return _cloneSolver();} |
| | 1841 | MipSolver* newSolver() {return _newSolver();} |
| | 1842 | MipSolver* cloneSolver() {return _cloneSolver();} |
| 1828 | 1843 | |
| 1829 | 1844 | protected: |
| 1830 | 1845 | |
| 1831 | | virtual MipBase* _newSolver() const = 0; |
| 1832 | | virtual MipBase* _cloneSolver() const = 0; |
| | 1846 | virtual MipSolver* _newSolver() const = 0; |
| | 1847 | virtual MipSolver* _cloneSolver() const = 0; |
| 1833 | 1848 | }; |
| 1834 | 1849 | |
| 1835 | 1850 | |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_clp.cc
|
a
|
b
|
|
| 65 | 65 | LpClp* copylp = new LpClp(*this); |
| 66 | 66 | return copylp; |
| 67 | 67 | } |
| | 68 | |
| | 69 | const char* LpClp::_solverName() const { return "LpClp"; } |
| 68 | 70 | |
| 69 | 71 | int LpClp::_addCol() { |
| 70 | 72 | _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0); |
| … |
… |
|
| 311 | 313 | return _prob->primalColumnSolution()[i]; |
| 312 | 314 | } |
| 313 | 315 | LpClp::Value LpClp::_getPrimalValue() const { |
| 314 | | return _prob->rawObjectiveValue(); |
| | 316 | return _prob->objectiveValue(); |
| 315 | 317 | } |
| 316 | 318 | |
| 317 | 319 | LpClp::Value LpClp::_getDual(int i) const { |
| … |
… |
|
| 399 | 401 | } |
| 400 | 402 | } |
| 401 | 403 | |
| 402 | | void LpClp::_setSense(SolverBase::Sense sense) { |
| | 404 | void LpClp::_setSense(LpClp::Sense sense) { |
| 403 | 405 | switch (sense) { |
| 404 | 406 | case MIN: |
| 405 | 407 | _prob->setOptimizationDirection(1); |
| … |
… |
|
| 410 | 412 | } |
| 411 | 413 | } |
| 412 | 414 | |
| 413 | | SolverBase::Sense LpClp::_getSense() const { |
| | 415 | LpClp::Sense LpClp::_getSense() const { |
| 414 | 416 | double dir = _prob->optimizationDirection(); |
| 415 | 417 | if (dir > 0.0) { |
| 416 | 418 | return MIN; |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_clp.h
|
a
|
b
|
|
| 39 | 39 | /// Clp library is an object oriented lp solver library developed at |
| 40 | 40 | /// the IBM. The CLP is part of the COIN-OR package and it can be |
| 41 | 41 | /// used with Common Public License. |
| 42 | | class LpClp : public LpBase { |
| | 42 | class LpClp : public LpSolver { |
| 43 | 43 | protected: |
| 44 | 44 | |
| 45 | 45 | ClpSimplex* _prob; |
| … |
… |
|
| 48 | 48 | std::map<std::string, int> _row_names_ref; |
| 49 | 49 | |
| 50 | 50 | public: |
| 51 | | |
| 52 | | typedef LpBase Parent; |
| 53 | 51 | |
| 54 | 52 | /// \e |
| 55 | 53 | LpClp(); |
| … |
… |
|
| 69 | 67 | protected: |
| 70 | 68 | |
| 71 | 69 | virtual LpClp* _newSolver() const; |
| 72 | | virtual LpClp* _cloneSolver() const ; |
| | 70 | virtual LpClp* _cloneSolver() const; |
| | 71 | |
| | 72 | virtual const char* _solverName() const; |
| 73 | 73 | |
| 74 | 74 | virtual int _addCol(); |
| 75 | 75 | virtual int _addRow(); |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_cplex.cc
|
a
|
b
|
|
| 69 | 69 | } |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | | CplexBase::CplexBase() : SolverBase() { |
| | 72 | CplexBase::CplexBase() : LpBase() { |
| 73 | 73 | int status; |
| 74 | 74 | _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | CplexBase::CplexBase(const CplexEnv& env) |
| 78 | | : SolverBase(), _env(env) { |
| | 78 | : LpBase(), _env(env) { |
| 79 | 79 | int status; |
| 80 | 80 | _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem"); |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | CplexBase::CplexBase(const CplexBase& cplex) |
| 84 | | : SolverBase() { |
| | 84 | : LpBase() { |
| 85 | 85 | int status; |
| 86 | 86 | _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status); |
| 87 | 87 | rows = cplex.rows; |
| … |
… |
|
| 395 | 395 | } |
| 396 | 396 | } |
| 397 | 397 | |
| 398 | | void CplexBase::_setObjCoeff(int i, SolverBase::Value obj_coef) |
| | 398 | void CplexBase::_setObjCoeff(int i, CplexBase::Value obj_coef) |
| 399 | 399 | { |
| 400 | 400 | CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef); |
| 401 | 401 | } |
| … |
… |
|
| 441 | 441 | // LpCplex members |
| 442 | 442 | |
| 443 | 443 | LpCplex::LpCplex() |
| 444 | | : SolverBase(), CplexBase(), LpBase() {} |
| | 444 | : LpBase(), CplexBase(), LpSolver() {} |
| 445 | 445 | |
| 446 | 446 | LpCplex::LpCplex(const CplexEnv& env) |
| 447 | | : SolverBase(), CplexBase(env), LpBase() {} |
| | 447 | : LpBase(), CplexBase(env), LpSolver() {} |
| 448 | 448 | |
| 449 | 449 | LpCplex::LpCplex(const LpCplex& other) |
| 450 | | : SolverBase(), CplexBase(other), LpBase() {} |
| | 450 | : LpBase(), CplexBase(other), LpSolver() {} |
| 451 | 451 | |
| 452 | 452 | LpCplex::~LpCplex() {} |
| 453 | 453 | |
| 454 | 454 | LpCplex* LpCplex::_newSolver() const { return new LpCplex; } |
| 455 | 455 | LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); } |
| | 456 | |
| | 457 | const char* LpCplex::_solverName() const { return "LpCplex"; } |
| 456 | 458 | |
| 457 | 459 | void LpCplex::_clear_temporals() { |
| 458 | 460 | _col_status.clear(); |
| … |
… |
|
| 796 | 798 | // MipCplex members |
| 797 | 799 | |
| 798 | 800 | MipCplex::MipCplex() |
| 799 | | : SolverBase(), CplexBase(), MipBase() { |
| | 801 | : LpBase(), CplexBase(), MipSolver() { |
| 800 | 802 | |
| 801 | 803 | #if CPX_VERSION < 800 |
| 802 | 804 | CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP); |
| … |
… |
|
| 806 | 808 | } |
| 807 | 809 | |
| 808 | 810 | MipCplex::MipCplex(const CplexEnv& env) |
| 809 | | : SolverBase(), CplexBase(env), MipBase() { |
| | 811 | : LpBase(), CplexBase(env), MipSolver() { |
| 810 | 812 | |
| 811 | 813 | #if CPX_VERSION < 800 |
| 812 | 814 | CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP); |
| … |
… |
|
| 817 | 819 | } |
| 818 | 820 | |
| 819 | 821 | MipCplex::MipCplex(const MipCplex& other) |
| 820 | | : SolverBase(), CplexBase(other), MipBase() {} |
| | 822 | : LpBase(), CplexBase(other), MipSolver() {} |
| 821 | 823 | |
| 822 | 824 | MipCplex::~MipCplex() {} |
| 823 | 825 | |
| 824 | 826 | MipCplex* MipCplex::_newSolver() const { return new MipCplex; } |
| 825 | 827 | MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); } |
| | 828 | |
| | 829 | const char* MipCplex::_solverName() const { return "MipCplex"; } |
| 826 | 830 | |
| 827 | 831 | void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) { |
| 828 | 832 | |
| … |
… |
|
| 843 | 847 | } |
| 844 | 848 | } |
| 845 | 849 | |
| 846 | | MipBase::ColTypes MipCplex::_getColType(int i) const { |
| | 850 | MipCplex::ColTypes MipCplex::_getColType(int i) const { |
| 847 | 851 | char t; |
| 848 | 852 | CPXgetctype (cplexEnv(), _prob, &t, i, i); |
| 849 | 853 | switch (t) { |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_cplex.h
|
a
|
b
|
|
| 77 | 77 | |
| 78 | 78 | /// \brief Base interface for the CPLEX LP and MIP solver |
| 79 | 79 | /// |
| 80 | | /// This class implements the common interface of the CPLEX LP and MIP solver. |
| 81 | | ///\ingroup lp_group |
| 82 | | class CplexBase : virtual public SolverBase { |
| | 80 | /// This class implements the common interface of the CPLEX LP and |
| | 81 | /// MIP solvers. |
| | 82 | /// \ingroup lp_group |
| | 83 | class CplexBase : virtual public LpBase { |
| 83 | 84 | protected: |
| 84 | | |
| 85 | | typedef SolverBase Parent; |
| 86 | 85 | |
| 87 | 86 | CplexEnv _env; |
| 88 | 87 | cpxlp* _prob; |
| … |
… |
|
| 161 | 160 | /// |
| 162 | 161 | /// This class implements an interface for the CPLEX LP solver. |
| 163 | 162 | ///\ingroup lp_group |
| 164 | | class LpCplex : public CplexBase, public LpBase { |
| | 163 | class LpCplex : public CplexBase, public LpSolver { |
| 165 | 164 | public: |
| 166 | 165 | /// \e |
| 167 | 166 | LpCplex(); |
| … |
… |
|
| 189 | 188 | |
| 190 | 189 | virtual LpCplex* _cloneSolver() const; |
| 191 | 190 | virtual LpCplex* _newSolver() const; |
| | 191 | |
| | 192 | virtual const char* _solverName() const; |
| 192 | 193 | |
| 193 | 194 | virtual SolveExitStatus _solve(); |
| 194 | 195 | virtual Value _getPrimal(int i) const; |
| … |
… |
|
| 221 | 222 | /// |
| 222 | 223 | /// This class implements an interface for the CPLEX MIP solver. |
| 223 | 224 | ///\ingroup lp_group |
| 224 | | class MipCplex : public CplexBase, public MipBase { |
| | 225 | class MipCplex : public CplexBase, public MipSolver { |
| 225 | 226 | public: |
| 226 | 227 | /// \e |
| 227 | 228 | MipCplex(); |
| … |
… |
|
| 237 | 238 | virtual MipCplex* _cloneSolver() const; |
| 238 | 239 | virtual MipCplex* _newSolver() const; |
| 239 | 240 | |
| | 241 | virtual const char* _solverName() const; |
| | 242 | |
| 240 | 243 | virtual ColTypes _getColType(int col) const; |
| 241 | 244 | virtual void _setColType(int col, ColTypes col_type); |
| 242 | 245 | |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_glpk.cc
|
a
|
b
|
|
| 28 | 28 | |
| 29 | 29 | // GlpkBase members |
| 30 | 30 | |
| 31 | | GlpkBase::GlpkBase() : SolverBase() { |
| | 31 | GlpkBase::GlpkBase() : LpBase() { |
| 32 | 32 | lp = glp_create_prob(); |
| 33 | 33 | glp_create_index(lp); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | | GlpkBase::GlpkBase(const GlpkBase &other) : SolverBase() { |
| | 36 | GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() { |
| 37 | 37 | lp = glp_create_prob(); |
| 38 | 38 | glp_copy_prob(lp, other.lp, GLP_ON); |
| 39 | 39 | glp_create_index(lp); |
| … |
… |
|
| 232 | 232 | |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | | SolverBase::Value GlpkBase::_getCoeff(int ix, int jx) const { |
| | 235 | GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const { |
| 236 | 236 | |
| 237 | 237 | int length = glp_get_mat_row(lp, ix, 0, 0); |
| 238 | 238 | |
| … |
… |
|
| 290 | 290 | } |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | | SolverBase::Value GlpkBase::_getColLowerBound(int i) const { |
| | 293 | GlpkBase::Value GlpkBase::_getColLowerBound(int i) const { |
| 294 | 294 | int b = glp_get_col_type(lp, i); |
| 295 | 295 | switch (b) { |
| 296 | 296 | case GLP_LO: |
| … |
… |
|
| 345 | 345 | |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | | SolverBase::Value GlpkBase::_getColUpperBound(int i) const { |
| | 348 | GlpkBase::Value GlpkBase::_getColUpperBound(int i) const { |
| 349 | 349 | int b = glp_get_col_type(lp, i); |
| 350 | 350 | switch (b) { |
| 351 | 351 | case GLP_UP: |
| … |
… |
|
| 398 | 398 | |
| 399 | 399 | } |
| 400 | 400 | |
| 401 | | SolverBase::Value GlpkBase::_getRowLowerBound(int i) const { |
| | 401 | GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const { |
| 402 | 402 | int b = glp_get_row_type(lp, i); |
| 403 | 403 | switch (b) { |
| 404 | 404 | case GLP_LO: |
| … |
… |
|
| 452 | 452 | } |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | | SolverBase::Value GlpkBase::_getRowUpperBound(int i) const { |
| | 455 | GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const { |
| 456 | 456 | int b = glp_get_row_type(lp, i); |
| 457 | 457 | switch (b) { |
| 458 | 458 | case GLP_UP: |
| … |
… |
|
| 488 | 488 | glp_set_obj_coef(lp, i, obj_coef); |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | | SolverBase::Value GlpkBase::_getObjCoeff(int i) const { |
| | 491 | GlpkBase::Value GlpkBase::_getObjCoeff(int i) const { |
| 492 | 492 | //i = 0 means the constant term (shift) |
| 493 | 493 | return glp_get_obj_coef(lp, i); |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | | void GlpkBase::_setSense(SolverBase::Sense sense) { |
| | 496 | void GlpkBase::_setSense(GlpkBase::Sense sense) { |
| 497 | 497 | switch (sense) { |
| 498 | 498 | case MIN: |
| 499 | 499 | glp_set_obj_dir(lp, GLP_MIN); |
| … |
… |
|
| 504 | 504 | } |
| 505 | 505 | } |
| 506 | 506 | |
| 507 | | SolverBase::Sense GlpkBase::_getSense() const { |
| | 507 | GlpkBase::Sense GlpkBase::_getSense() const { |
| 508 | 508 | switch(glp_get_obj_dir(lp)) { |
| 509 | 509 | case GLP_MIN: |
| 510 | 510 | return MIN; |
| … |
… |
|
| 512 | 512 | return MAX; |
| 513 | 513 | default: |
| 514 | 514 | LEMON_ASSERT(false, "Wrong sense"); |
| 515 | | return SolverBase::Sense(); |
| | 515 | return GlpkBase::Sense(); |
| 516 | 516 | } |
| 517 | 517 | } |
| 518 | 518 | |
| … |
… |
|
| 525 | 525 | // LpGlpk members |
| 526 | 526 | |
| 527 | 527 | LpGlpk::LpGlpk() |
| 528 | | : SolverBase(), GlpkBase(), LpBase() { |
| | 528 | : LpBase(), GlpkBase(), LpSolver() { |
| 529 | 529 | messageLevel(MESSAGE_NO_OUTPUT); |
| 530 | 530 | } |
| 531 | 531 | |
| 532 | 532 | LpGlpk::LpGlpk(const LpGlpk& other) |
| 533 | | : SolverBase(other), GlpkBase(other), LpBase(other) { |
| | 533 | : LpBase(other), GlpkBase(other), LpSolver(other) { |
| 534 | 534 | messageLevel(MESSAGE_NO_OUTPUT); |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | 537 | LpGlpk* LpGlpk::_newSolver() const { return new LpGlpk; } |
| 538 | | LpGlpk* LpGlpk::_cloneSolver() const {return new LpGlpk(*this); } |
| | 538 | LpGlpk* LpGlpk::_cloneSolver() const { return new LpGlpk(*this); } |
| | 539 | |
| | 540 | const char* LpGlpk::_solverName() const { return "LpGlpk"; } |
| 539 | 541 | |
| 540 | 542 | void LpGlpk::_clear_temporals() { |
| 541 | 543 | _primal_ray.clear(); |
| … |
… |
|
| 822 | 824 | // MipGlpk members |
| 823 | 825 | |
| 824 | 826 | MipGlpk::MipGlpk() |
| 825 | | : SolverBase(), GlpkBase(), MipBase() { |
| | 827 | : LpBase(), GlpkBase(), MipSolver() { |
| 826 | 828 | messageLevel(MESSAGE_NO_OUTPUT); |
| 827 | 829 | } |
| 828 | 830 | |
| 829 | 831 | MipGlpk::MipGlpk(const MipGlpk& other) |
| 830 | | : SolverBase(), GlpkBase(other), MipBase() { |
| | 832 | : LpBase(), GlpkBase(other), MipSolver() { |
| 831 | 833 | messageLevel(MESSAGE_NO_OUTPUT); |
| 832 | 834 | } |
| 833 | 835 | |
| … |
… |
|
| 941 | 943 | MipGlpk* MipGlpk::_newSolver() const { return new MipGlpk; } |
| 942 | 944 | MipGlpk* MipGlpk::_cloneSolver() const {return new MipGlpk(*this); } |
| 943 | 945 | |
| | 946 | const char* MipGlpk::_solverName() const { return "MipGlpk"; } |
| | 947 | |
| 944 | 948 | void MipGlpk::messageLevel(MessageLevel m) { |
| 945 | 949 | _message_level = m; |
| 946 | 950 | } |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_glpk.h
|
a
|
b
|
|
| 39 | 39 | /// |
| 40 | 40 | /// This class implements the common interface of the GLPK LP and MIP solver. |
| 41 | 41 | /// \ingroup lp_group |
| 42 | | class GlpkBase : virtual public SolverBase { |
| | 42 | class GlpkBase : virtual public LpBase { |
| 43 | 43 | protected: |
| 44 | 44 | |
| 45 | 45 | typedef glp_prob LPX; |
| 46 | 46 | glp_prob* lp; |
| 47 | | |
| 48 | | typedef LpBase Parent; |
| 49 | 47 | |
| 50 | 48 | GlpkBase(); |
| 51 | 49 | GlpkBase(const GlpkBase&); |
| … |
… |
|
| 121 | 119 | /// |
| 122 | 120 | /// This class implements an interface for the GLPK LP solver. |
| 123 | 121 | ///\ingroup lp_group |
| 124 | | class LpGlpk : public GlpkBase, public LpBase { |
| | 122 | class LpGlpk : public GlpkBase, public LpSolver { |
| 125 | 123 | public: |
| 126 | 124 | |
| 127 | 125 | ///\e |
| … |
… |
|
| 141 | 139 | virtual LpGlpk* _cloneSolver() const; |
| 142 | 140 | virtual LpGlpk* _newSolver() const; |
| 143 | 141 | |
| 144 | | ///\todo It should be clarified |
| 145 | | /// |
| | 142 | virtual const char* _solverName() const; |
| | 143 | |
| 146 | 144 | virtual SolveExitStatus _solve(); |
| 147 | 145 | virtual Value _getPrimal(int i) const; |
| 148 | 146 | virtual Value _getDual(int i) const; |
| … |
… |
|
| 205 | 203 | /// |
| 206 | 204 | /// This class implements an interface for the GLPK MIP solver. |
| 207 | 205 | ///\ingroup lp_group |
| 208 | | class MipGlpk : public GlpkBase, public MipBase { |
| | 206 | class MipGlpk : public GlpkBase, public MipSolver { |
| 209 | 207 | public: |
| 210 | 208 | |
| 211 | 209 | ///\e |
| … |
… |
|
| 217 | 215 | |
| 218 | 216 | virtual MipGlpk* _cloneSolver() const; |
| 219 | 217 | virtual MipGlpk* _newSolver() const; |
| | 218 | |
| | 219 | virtual const char* _solverName() const; |
| 220 | 220 | |
| 221 | 221 | virtual ColTypes _getColType(int col) const; |
| 222 | 222 | virtual void _setColType(int col, ColTypes col_type); |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_skeleton.cc
|
a
|
b
|
|
| 111 | 111 | LpSkeleton* LpSkeleton::_cloneSolver() const |
| 112 | 112 | { return static_cast<LpSkeleton*>(0); } |
| 113 | 113 | |
| | 114 | const char* LpSkeleton::_solverName() const { return "LpSkeleton"; } |
| | 115 | |
| 114 | 116 | MipSkeleton::SolveExitStatus MipSkeleton::_solve() |
| 115 | 117 | { return SOLVED; } |
| 116 | 118 | |
| … |
… |
|
| 126 | 128 | MipSkeleton* MipSkeleton::_cloneSolver() const |
| 127 | 129 | { return static_cast<MipSkeleton*>(0); } |
| 128 | 130 | |
| | 131 | const char* MipSkeleton::_solverName() const { return "MipSkeleton"; } |
| | 132 | |
| 129 | 133 | } //namespace lemon |
| 130 | 134 | |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_skeleton.h
|
a
|
b
|
|
| 26 | 26 | namespace lemon { |
| 27 | 27 | |
| 28 | 28 | ///A skeleton class to implement LP solver interfaces |
| 29 | | class SkeletonSolverBase : public virtual SolverBase { |
| | 29 | class SkeletonSolverBase : public virtual LpBase { |
| 30 | 30 | int col_num,row_num; |
| 31 | 31 | |
| 32 | 32 | protected: |
| … |
… |
|
| 140 | 140 | /// |
| 141 | 141 | /// This class implements an interface for a skeleton LP solver. |
| 142 | 142 | ///\ingroup lp_group |
| 143 | | class LpSkeleton : public SkeletonSolverBase, public LpBase { |
| | 143 | class LpSkeleton : public SkeletonSolverBase, public LpSolver { |
| 144 | 144 | public: |
| 145 | | LpSkeleton() : SkeletonSolverBase(), LpBase() {} |
| | 145 | LpSkeleton() : SkeletonSolverBase(), LpSolver() {} |
| 146 | 146 | |
| 147 | 147 | protected: |
| 148 | 148 | |
| … |
… |
|
| 176 | 176 | virtual LpSkeleton* _newSolver() const; |
| 177 | 177 | ///\e |
| 178 | 178 | virtual LpSkeleton* _cloneSolver() const; |
| | 179 | ///\e |
| | 180 | virtual const char* _solverName() const; |
| 179 | 181 | |
| 180 | 182 | }; |
| 181 | 183 | |
| … |
… |
|
| 183 | 185 | /// |
| 184 | 186 | /// This class implements an interface for a skeleton MIP solver. |
| 185 | 187 | ///\ingroup lp_group |
| 186 | | class MipSkeleton : public SkeletonSolverBase, public MipBase { |
| | 188 | class MipSkeleton : public SkeletonSolverBase, public MipSolver { |
| 187 | 189 | public: |
| 188 | | MipSkeleton() : SkeletonSolverBase(), MipBase() {} |
| | 190 | MipSkeleton() : SkeletonSolverBase(), MipSolver() {} |
| 189 | 191 | |
| 190 | 192 | protected: |
| 191 | 193 | ///\e |
| … |
… |
|
| 217 | 219 | |
| 218 | 220 | ///\e |
| 219 | 221 | virtual MipSkeleton* _cloneSolver() const; |
| | 222 | ///\e |
| | 223 | virtual const char* _solverName() const; |
| 220 | 224 | |
| 221 | 225 | }; |
| 222 | 226 | |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_soplex.cc
|
a
|
b
|
|
| 26 | 26 | ///\brief Implementation of the LEMON-SOPLEX lp solver interface. |
| 27 | 27 | namespace lemon { |
| 28 | 28 | |
| 29 | | LpSoplex::LpSoplex() |
| 30 | | : SolverBase(), LpBase() { |
| | 29 | LpSoplex::LpSoplex() { |
| 31 | 30 | soplex = new soplex::SoPlex; |
| 32 | 31 | } |
| 33 | 32 | |
| … |
… |
|
| 35 | 34 | delete soplex; |
| 36 | 35 | } |
| 37 | 36 | |
| 38 | | LpSoplex::LpSoplex(const LpSoplex& lp) |
| 39 | | : SolverBase(), LpBase() { |
| | 37 | LpSoplex::LpSoplex(const LpSoplex& lp) { |
| 40 | 38 | rows = lp.rows; |
| 41 | 39 | cols = lp.cols; |
| 42 | 40 | |
| … |
… |
|
| 65 | 63 | LpSoplex* newlp = new LpSoplex(*this); |
| 66 | 64 | return newlp; |
| 67 | 65 | } |
| | 66 | |
| | 67 | const char* LpSoplex::_solverName() const { return "LpSoplex"; } |
| 68 | 68 | |
| 69 | 69 | int LpSoplex::_addCol() { |
| 70 | 70 | soplex::LPCol c; |
diff -r f259f5b9d9c7 -r 9347462c3106 lemon/lp_soplex.h
|
a
|
b
|
|
| 43 | 43 | /// developed at the Konrad-Zuse-Zentrum für Informationstechnik |
| 44 | 44 | /// Berlin (ZIB). You can find detailed information about it at the |
| 45 | 45 | /// <tt>http://soplex.zib.de</tt> address. |
| 46 | | class LpSoplex : public LpBase { |
| | 46 | class LpSoplex : public LpSolver { |
| 47 | 47 | private: |
| 48 | 48 | |
| 49 | 49 | soplex::SoPlex* soplex; |
| … |
… |
|
| 67 | 67 | |
| 68 | 68 | public: |
| 69 | 69 | |
| 70 | | typedef LpBase Parent; |
| 71 | | |
| 72 | | |
| 73 | 70 | /// \e |
| 74 | 71 | LpSoplex(); |
| 75 | 72 | /// \e |
| … |
… |
|
| 80 | 77 | protected: |
| 81 | 78 | |
| 82 | 79 | virtual LpSoplex* _newSolver() const; |
| 83 | | virtual LpSoplex* _cloneSolver() const ; |
| | 80 | virtual LpSoplex* _cloneSolver() const; |
| | 81 | |
| | 82 | virtual const char* _solverName() const; |
| 84 | 83 | |
| 85 | 84 | virtual int _addCol(); |
| 86 | 85 | virtual int _addRow(); |
diff -r f259f5b9d9c7 -r 9347462c3106 test/lp_test.cc
|
a
|
b
|
|
| 43 | 43 | |
| 44 | 44 | using namespace lemon; |
| 45 | 45 | |
| 46 | | void lpTest(LpBase & lp) |
| | 46 | void lpTest(LpSolver& lp) |
| 47 | 47 | { |
| 48 | 48 | |
| 49 | | typedef LpBase LP; |
| | 49 | typedef LpSolver LP; |
| 50 | 50 | |
| 51 | 51 | std::vector<LP::Col> x(10); |
| 52 | 52 | // for(int i=0;i<10;i++) x.push_back(lp.addCol()); |
| … |
… |
|
| 195 | 195 | tolerance=0.02; |
| 196 | 196 | e.simplify(tolerance); |
| 197 | 197 | buf << "Coeff. of p2 should be 0"; |
| 198 | | check(const_cast<const LpBase::Expr&>(e)[p2]==0, buf.str()); |
| | 198 | check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str()); |
| 199 | 199 | |
| 200 | 200 | |
| 201 | 201 | } |
| … |
… |
|
| 235 | 235 | |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | | void solveAndCheck(LpBase& lp, LpBase::ProblemType stat, |
| | 238 | void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat, |
| 239 | 239 | double exp_opt) { |
| 240 | 240 | using std::string; |
| 241 | 241 | lp.solve(); |
| … |
… |
|
| 245 | 245 | |
| 246 | 246 | check(lp.primalType()==stat, buf.str()); |
| 247 | 247 | |
| 248 | | if (stat == LpBase::OPTIMAL) { |
| | 248 | if (stat == LpSolver::OPTIMAL) { |
| 249 | 249 | std::ostringstream sbuf; |
| 250 | 250 | sbuf << "Wrong optimal value: the right optimum is " << exp_opt; |
| 251 | 251 | check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str()); |
| 252 | 252 | } |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | | void aTest(LpBase & lp) |
| | 255 | void aTest(LpSolver & lp) |
| 256 | 256 | { |
| 257 | | typedef LpBase LP; |
| | 257 | typedef LpSolver LP; |
| 258 | 258 | |
| 259 | 259 | //The following example is very simple |
| 260 | 260 | |
| 261 | | typedef LpBase::Row Row; |
| 262 | | typedef LpBase::Col Col; |
| | 261 | typedef LpSolver::Row Row; |
| | 262 | typedef LpSolver::Col Col; |
| 263 | 263 | |
| 264 | 264 | |
| 265 | 265 | Col x1 = lp.addCol(); |
| … |
… |
|
| 285 | 285 | check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!"); |
| 286 | 286 | check(lp.colLowerBound(x1)==0, |
| 287 | 287 | "The lower bound for variable x1 should be 0."); |
| 288 | | check(lp.colUpperBound(x1)==LpBase::INF, |
| | 288 | check(lp.colUpperBound(x1)==LpSolver::INF, |
| 289 | 289 | "The upper bound for variable x1 should be infty."); |
| 290 | | check(lp.rowLowerBound(upright) == -LpBase::INF, |
| | 290 | check(lp.rowLowerBound(upright) == -LpSolver::INF, |
| 291 | 291 | "The lower bound for the first row should be -infty."); |
| 292 | 292 | check(lp.rowUpperBound(upright)==1, |
| 293 | 293 | "The upper bound for the first row should be 1."); |
| 294 | | LpBase::Expr e = lp.row(upright); |
| | 294 | LpSolver::Expr e = lp.row(upright); |
| 295 | 295 | check(e[x1] == 1, "The first coefficient should 1."); |
| 296 | 296 | check(e[x2] == 2, "The second coefficient should 1."); |
| 297 | 297 | |
| … |
… |
|
| 300 | 300 | check(e[x1] == 1, "The first coefficient should 1."); |
| 301 | 301 | check(e[x2] == 1, "The second coefficient should 1."); |
| 302 | 302 | |
| 303 | | LpBase::DualExpr de = lp.col(x1); |
| | 303 | LpSolver::DualExpr de = lp.col(x1); |
| 304 | 304 | check( de[upright] == 1, "The first coefficient should 1."); |
| 305 | 305 | |
| 306 | | LpBase* clp = lp.cloneSolver(); |
| | 306 | LpSolver* clp = lp.cloneSolver(); |
| 307 | 307 | |
| 308 | 308 | //Testing the problem retrieving routines |
| 309 | 309 | check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!"); |
| … |
… |
|
| 312 | 312 | // std::cout<<lp.colLowerBound(x1)<<std::endl; |
| 313 | 313 | check(clp->colLowerBound(x1)==0, |
| 314 | 314 | "The lower bound for variable x1 should be 0."); |
| 315 | | check(clp->colUpperBound(x1)==LpBase::INF, |
| | 315 | check(clp->colUpperBound(x1)==LpSolver::INF, |
| 316 | 316 | "The upper bound for variable x1 should be infty."); |
| 317 | 317 | |
| 318 | | check(lp.rowLowerBound(upright)==-LpBase::INF, |
| | 318 | check(lp.rowLowerBound(upright)==-LpSolver::INF, |
| 319 | 319 | "The lower bound for the first row should be -infty."); |
| 320 | 320 | check(lp.rowUpperBound(upright)==1, |
| 321 | 321 | "The upper bound for the first row should be 1."); |
| … |
… |
|
| 331 | 331 | //Maximization of x1+x2 |
| 332 | 332 | //over the triangle with vertices (0,0) (0,1) (1,0) |
| 333 | 333 | double expected_opt=1; |
| 334 | | solveAndCheck(lp, LpBase::OPTIMAL, expected_opt); |
| | 334 | solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt); |
| 335 | 335 | |
| 336 | 336 | //Minimization |
| 337 | 337 | lp.sense(lp.MIN); |
| 338 | 338 | expected_opt=0; |
| 339 | | solveAndCheck(lp, LpBase::OPTIMAL, expected_opt); |
| | 339 | solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt); |
| 340 | 340 | |
| 341 | 341 | //Vertex (-1,0) instead of (0,0) |
| 342 | | lp.colLowerBound(x1, -LpBase::INF); |
| | 342 | lp.colLowerBound(x1, -LpSolver::INF); |
| 343 | 343 | expected_opt=-1; |
| 344 | | solveAndCheck(lp, LpBase::OPTIMAL, expected_opt); |
| | 344 | solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt); |
| 345 | 345 | |
| 346 | 346 | //Erase one constraint and return to maximization |
| 347 | 347 | lp.erase(upright); |
| 348 | 348 | lp.sense(lp.MAX); |
| 349 | | expected_opt=LpBase::INF; |
| 350 | | solveAndCheck(lp, LpBase::UNBOUNDED, expected_opt); |
| | 349 | expected_opt=LpSolver::INF; |
| | 350 | solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt); |
| 351 | 351 | |
| 352 | 352 | //Infeasibilty |
| 353 | 353 | lp.addRow(x1+x2 <=-2); |
| 354 | | solveAndCheck(lp, LpBase::INFEASIBLE, expected_opt); |
| | 354 | solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt); |
| 355 | 355 | |
| 356 | 356 | } |
| 357 | 357 | |
diff -r f259f5b9d9c7 -r 9347462c3106 test/mip_test.cc
|
a
|
b
|
|
| 34 | 34 | |
| 35 | 35 | using namespace lemon; |
| 36 | 36 | |
| 37 | | void solveAndCheck(MipBase& mip, MipBase::ProblemType stat, |
| | 37 | void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat, |
| 38 | 38 | double exp_opt) { |
| 39 | 39 | using std::string; |
| 40 | 40 | |
| … |
… |
|
| 47 | 47 | // itoa(stat,buf1, 10); |
| 48 | 48 | check(mip.type()==stat, buf.str()); |
| 49 | 49 | |
| 50 | | if (stat == MipBase::OPTIMAL) { |
| | 50 | if (stat == MipSolver::OPTIMAL) { |
| 51 | 51 | std::ostringstream sbuf; |
| 52 | 52 | buf << "Wrong optimal value: the right optimum is " << exp_opt; |
| 53 | 53 | check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str()); |
| … |
… |
|
| 55 | 55 | } |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | | void aTest(MipBase& mip) |
| | 58 | void aTest(MipSolver& mip) |
| 59 | 59 | { |
| 60 | 60 | //The following example is very simple |
| 61 | 61 | |
| 62 | 62 | |
| 63 | | typedef MipBase::Row Row; |
| 64 | | typedef MipBase::Col Col; |
| | 63 | typedef MipSolver::Row Row; |
| | 64 | typedef MipSolver::Col Col; |
| 65 | 65 | |
| 66 | 66 | |
| 67 | 67 | |
| … |
… |
|
| 89 | 89 | //Maximization of x1 |
| 90 | 90 | //over the triangle with vertices (0,0),(4/5,2/5),(0,2) |
| 91 | 91 | double expected_opt=4.0/5.0; |
| 92 | | solveAndCheck(mip, MipBase::OPTIMAL, expected_opt); |
| | 92 | solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt); |
| 93 | 93 | |
| 94 | 94 | //Restrict x2 to integer |
| 95 | | mip.colType(x2,MipBase::INTEGER); |
| | 95 | mip.colType(x2,MipSolver::INTEGER); |
| 96 | 96 | expected_opt=1.0/2.0; |
| 97 | | solveAndCheck(mip, MipBase::OPTIMAL, expected_opt); |
| | 97 | solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt); |
| 98 | 98 | |
| 99 | 99 | |
| 100 | 100 | //Restrict both to integer |
| 101 | | mip.colType(x1,MipBase::INTEGER); |
| | 101 | mip.colType(x1,MipSolver::INTEGER); |
| 102 | 102 | expected_opt=0; |
| 103 | | solveAndCheck(mip, MipBase::OPTIMAL, expected_opt); |
| | 103 | solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt); |
| 104 | 104 | |
| 105 | 105 | |
| 106 | 106 | |
| … |
… |
|
| 111 | 111 | { |
| 112 | 112 | |
| 113 | 113 | #ifdef HAVE_GLPK |
| 114 | | MipGlpk mip1; |
| 115 | | aTest(mip1); |
| | 114 | { |
| | 115 | MipGlpk mip1; |
| | 116 | aTest(mip1); |
| | 117 | } |
| 116 | 118 | #endif |
| 117 | 119 | |
| 118 | 120 | #ifdef HAVE_CPLEX |
| 119 | | MipCplex mip2; |
| 120 | | aTest(mip2); |
| | 121 | try { |
| | 122 | MipCplex mip2; |
| | 123 | aTest(mip2); |
| | 124 | } catch (CplexEnv::LicenseError& error) { |
| | 125 | #ifdef LEMON_FORCE_CPLEX_CHECK |
| | 126 | check(false, error.what()); |
| | 127 | #else |
| | 128 | std::cerr << error.what() << std::endl; |
| | 129 | std::cerr << "Cplex license check failed, lp check skipped" << std::endl; |
| | 130 | #endif |
| | 131 | } |
| 121 | 132 | #endif |
| 122 | 133 | |
| 123 | 134 | return 0; |