# 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; |