2 #ifndef LEMON_LP_SOLVER_WRAPPER_H
3 #define LEMON_LP_SOLVER_WRAPPER_H
7 ///\brief Dijkstra algorithm.
26 //#include <sage_graph.h>
27 //#include <lemon/list_graph.h>
28 //#include <lemon/graph_wrapper.h>
29 #include <lemon/invalid.h>
30 //#include <bfs_dfs.h>
32 //#include <lemon/max_flow.h>
33 //#include <augmenting_flow.h>
34 //#include <iter_map.h>
45 /// \brief A partitioned vector with iterable classes.
47 /// This class implements a container in which the data is stored in an
48 /// stl vector, the range is partitioned into sets and each set is
49 /// doubly linked in a list.
50 /// That is, each class is iterable by lemon iterators, and any member of
51 /// the vector can bo moved to an other class.
53 class IterablePartition {
57 int prev; //invalid az -1
60 std::vector<Node> nodes;
65 std::vector<Tip> tips;
67 /// The classes are indexed by integers from \c 0 to \c classNum()-1.
68 int classNum() const { return tips.size(); }
69 /// This lemon style iterator iterates through a class.
71 /// Constructor. The number of classes is to be given which is fixed
72 /// over the life of the container.
73 /// The partition classes are indexed from 0 to class_num-1.
74 IterablePartition(int class_num) {
75 for (int i=0; i<class_num; ++i) {
82 void befuz(ClassIt it, int class_id) {
83 if (tips[class_id].first==-1) {
84 if (tips[class_id].last==-1) {
85 nodes[it.i].prev=nodes[it.i].next=-1;
86 tips[class_id].first=tips[class_id].last=it.i;
89 nodes[it.i].prev=tips[class_id].last;
91 nodes[tips[class_id].last].next=it.i;
92 tips[class_id].last=it.i;
95 void kifuz(ClassIt it, int class_id) {
96 if (tips[class_id].first==it.i) {
97 if (tips[class_id].last==it.i) {
98 tips[class_id].first=tips[class_id].last=-1;
100 tips[class_id].first=nodes[it.i].next;
101 nodes[nodes[it.i].next].prev=-1;
104 if (tips[class_id].last==it.i) {
105 tips[class_id].last=nodes[it.i].prev;
106 nodes[nodes[it.i].prev].next=-1;
108 nodes[nodes[it.i].next].prev=nodes[it.i].prev;
109 nodes[nodes[it.i].prev].next=nodes[it.i].next;
114 /// A new element with data \c t is pushed into the vector and into class
116 ClassIt push_back(const T& t, int class_id) {
120 int i=nodes.size()-1;
124 /// A member is moved to an other class.
125 void set(ClassIt it, int old_class_id, int new_class_id) {
126 kifuz(it.i, old_class_id);
127 befuz(it.i, new_class_id);
129 /// Returns the data pointed by \c it.
130 T& operator[](ClassIt it) { return nodes[it.i].data; }
131 /// Returns the data pointed by \c it.
132 const T& operator[](ClassIt it) const { return nodes[it.i].data; }
135 friend class IterablePartition;
139 /// Default constructor.
141 /// This constructor constructs an iterator which points
142 /// to the member of th container indexed by the integer _i.
143 ClassIt(const int& _i) : i(_i) { }
144 /// Invalid constructor.
145 ClassIt(const Invalid&) : i(-1) { }
147 /// First member of class \c class_id.
148 ClassIt& first(ClassIt& it, int class_id) const {
149 it.i=tips[class_id].first;
153 ClassIt& next(ClassIt& it) const {
154 it.i=nodes[it.i].next;
157 /// True iff the iterator is valid.
158 bool valid(const ClassIt& it) const { return it.i!=-1; }
161 template <typename _Col, typename _Value>
164 template <typename _Col, typename _Value>
166 template <typename _C, typename _V>
172 SmallExpr(_Col _col) : col(_col), value(1) {
174 SmallExpr& operator *= (_Value _value) {
178 // template <typename _C, typename _V>
179 // friend SmallExpr<_C, _V> operator* (_V _value,
180 // const SmallExpr<_C, _V>& expr);
181 template <typename _C, typename _V>
182 friend std::ostream& operator<<(std::ostream& os,
183 const SmallExpr<_C, _V>& expr);
186 template <typename _Col, typename _Value>
187 SmallExpr<_Col, _Value>
188 operator* (_Value value,
189 const SmallExpr<_Col, _Value>& expr) {
190 SmallExpr<_Col, _Value> tmp;
196 template <typename _Col, typename _Value>
197 std::ostream& operator<<(std::ostream& os,
198 const SmallExpr<_Col, _Value>& expr) {
199 os << expr.value << "*" << expr.col;
203 template <typename _Col, typename _Value>
207 typename std::map<_Col, _Value> Data;
211 Expr(SmallExpr<_Col, _Value> expr) {
212 data.insert(std::make_pair(expr.col, expr.value));
215 // data.insert(std::make_pair(col, 1));
217 Expr& operator*=(_Value _value) {
218 for (typename Data::iterator i=data.begin();
219 i!=data.end(); ++i) {
220 (*i).second *= _value;
224 Expr& operator+=(SmallExpr<_Col, _Value> expr) {
225 typename Data::iterator i=data.find(expr.col);
227 data.insert(std::make_pair(expr.col, expr.value));
229 (*i).second+=expr.value;
233 // template <typename _C, typename _V>
234 // friend Expr<_C, _V> operator*(_V _value, const Expr<_C, _V>& expr);
235 template <typename _C, typename _V>
236 friend std::ostream& operator<<(std::ostream& os,
237 const Expr<_C, _V>& expr);
240 template <typename _Col, typename _Value>
241 Expr<_Col, _Value> operator*(_Value _value,
242 const Expr<_Col, _Value>& expr) {
243 Expr<_Col, _Value> tmp;
249 template <typename _Col, typename _Value>
250 std::ostream& operator<<(std::ostream& os,
251 const Expr<_Col, _Value>& expr) {
252 for (typename Expr<_Col, _Value>::Data::const_iterator i=
254 i!=expr.data.end(); ++i) {
255 os << (*i).second << "*" << (*i).first << " ";
262 template <typename _Value>
266 typedef _Value Value;
268 typedef IterablePartition<int>::ClassIt RowIt;
270 typedef IterablePartition<int>::ClassIt ColIt;
273 IterablePartition<int> row_iter_map;
275 IterablePartition<int> col_iter_map;
277 const int VALID_CLASS;
279 const int INVALID_CLASS;
282 LPSolverBase() : row_iter_map(2),
284 VALID_CLASS(0), INVALID_CLASS(1) { }
286 virtual ~LPSolverBase() { }
288 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
292 virtual void setMinimize() = 0;
294 virtual void setMaximize() = 0;
296 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
300 virtual int _addRow() = 0;
302 virtual int _addCol() = 0;
304 virtual void _setRowCoeffs(int i,
305 std::vector<std::pair<int, double> > coeffs) = 0;
307 virtual void _setColCoeffs(int i,
308 std::vector<std::pair<int, double> > coeffs) = 0;
310 virtual void _eraseCol(int i) = 0;
312 virtual void _eraseRow(int i) = 0;
315 enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
318 virtual void _setColBounds(int i, Bound bound,
319 _Value lo, _Value up) = 0;
321 virtual void _setRowBounds(int i, Bound bound,
322 _Value lo, _Value up) = 0;
324 virtual void _setObjCoef(int i, _Value obj_coef) = 0;
326 virtual _Value _getObjCoef(int i) = 0;
328 //LOW LEVEL, SOLUTION RETRIEVING FUNCTIONS
331 virtual _Value _getPrimal(int i) = 0;
333 //HIGH LEVEL INTERFACE, MATRIX MANIPULATING FUNTIONS
340 row_iter_map.first(row_it, INVALID_CLASS);
341 if (row_iter_map.valid(row_it)) { //van hasznalhato hely
342 row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
343 row_iter_map[row_it]=i;
344 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
345 row_it=row_iter_map.push_back(i, VALID_CLASS);
353 col_iter_map.first(col_it, INVALID_CLASS);
354 if (col_iter_map.valid(col_it)) { //van hasznalhato hely
355 col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
356 col_iter_map[col_it]=i;
357 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
358 col_it=col_iter_map.push_back(i, VALID_CLASS);
363 template <typename Begin, typename End>
364 void setRowCoeffs(RowIt row_it, Begin begin, End end) {
365 std::vector<std::pair<int, double> > coeffs;
366 for ( ; begin!=end; ++begin) {
367 coeffs.push_back(std::
368 make_pair(col_iter_map[begin->first], begin->second));
370 _setRowCoeffs(row_iter_map[row_it], coeffs);
373 template <typename Begin, typename End>
374 void setColCoeffs(ColIt col_it, Begin begin, End end) {
375 std::vector<std::pair<int, double> > coeffs;
376 for ( ; begin!=end; ++begin) {
377 coeffs.push_back(std::
378 make_pair(row_iter_map[begin->first], begin->second));
380 _setColCoeffs(col_iter_map[col_it], coeffs);
383 void eraseCol(const ColIt& col_it) {
384 col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
386 cols[1]=col_iter_map[col_it];
388 col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
390 for (col_iter_map.first(it, VALID_CLASS);
391 col_iter_map.valid(it); col_iter_map.next(it)) {
392 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
396 void eraseRow(const RowIt& row_it) {
397 row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
399 rows[1]=row_iter_map[row_it];
401 row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
403 for (row_iter_map.first(it, VALID_CLASS);
404 row_iter_map.valid(it); row_iter_map.next(it)) {
405 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
409 void setColBounds(const ColIt& col_it, Bound bound,
410 _Value lo, _Value up) {
411 _setColBounds(col_iter_map[col_it], bound, lo, up);
414 void setRowBounds(const RowIt& row_it, Bound bound,
415 _Value lo, _Value up) {
416 _setRowBounds(row_iter_map[row_it], bound, lo, up);
419 void setObjCoef(const ColIt& col_it, _Value obj_coef) {
420 _setObjCoef(col_iter_map[col_it], obj_coef);
423 _Value getObjCoef(const ColIt& col_it) {
424 return _getObjCoef(col_iter_map[col_it]);
430 virtual void solveSimplex() = 0;
432 virtual void solvePrimalSimplex() = 0;
434 virtual void solveDualSimplex() = 0;
437 //HIGH LEVEL, SOLUTION RETRIEVING FUNCTIONS
440 _Value getPrimal(const ColIt& col_it) {
441 return _getPrimal(col_iter_map[col_it]);
444 virtual _Value getObjVal() = 0;
449 virtual int rowNum() const = 0;
451 virtual int colNum() const = 0;
453 virtual int warmUp() = 0;
455 virtual void printWarmUpStatus(int i) = 0;
457 virtual int getPrimalStatus() = 0;
459 virtual void printPrimalStatus(int i) = 0;
461 virtual int getDualStatus() = 0;
463 virtual void printDualStatus(int i) = 0;
464 /// Returns the status of the slack variable assigned to row \c row_it.
465 virtual int getRowStat(const RowIt& row_it) = 0;
467 virtual void printRowStatus(int i) = 0;
468 /// Returns the status of the variable assigned to column \c col_it.
469 virtual int getColStat(const ColIt& col_it) = 0;
471 virtual void printColStatus(int i) = 0;
475 /// \brief Wrappers for LP solvers
477 /// This class implements a lemon wrapper for glpk.
478 /// Later other LP-solvers will be wrapped into lemon.
479 /// The aim of this class is to give a general surface to different
480 /// solvers, i.e. it makes possible to write algorithms using LP's,
481 /// in which the solver can be changed to an other one easily.
482 class LPGLPK : public LPSolverBase<double> {
484 typedef LPSolverBase<double> Parent;
493 lp(lpx_create_prob()) {
494 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
501 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
505 lpx_set_obj_dir(lp, LPX_MIN);
509 lpx_set_obj_dir(lp, LPX_MAX);
512 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
517 return lpx_add_cols(lp, 1);
521 return lpx_add_rows(lp, 1);
524 virtual void _setRowCoeffs(int i,
525 std::vector<std::pair<int, double> > coeffs) {
526 int mem_length=1+colNum();
527 int* indices = new int[mem_length];
528 double* doubles = new double[mem_length];
530 for (std::vector<std::pair<int, double> >::
531 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
533 indices[length]=it->first;
534 doubles[length]=it->second;
535 // std::cout << " " << indices[length] << " "
536 // << doubles[length] << std::endl;
538 // std::cout << i << " " << length << std::endl;
539 lpx_set_mat_row(lp, i, length, indices, doubles);
544 virtual void _setColCoeffs(int i,
545 std::vector<std::pair<int, double> > coeffs) {
546 int mem_length=1+rowNum();
547 int* indices = new int[mem_length];
548 double* doubles = new double[mem_length];
550 for (std::vector<std::pair<int, double> >::
551 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
553 indices[length]=it->first;
554 doubles[length]=it->second;
556 lpx_set_mat_col(lp, i, length, indices, doubles);
561 virtual void _eraseCol(int i) {
564 lpx_del_cols(lp, 1, cols);
566 virtual void _eraseRow(int i) {
569 lpx_del_rows(lp, 1, rows);
571 virtual void _setColBounds(int i, Bound bound,
572 double lo, double up) {
575 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
578 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
581 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
584 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
587 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
591 virtual void _setRowBounds(int i, Bound bound,
592 double lo, double up) {
595 lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
598 lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
601 lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
604 lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
607 lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
613 virtual double _getObjCoef(int i) {
614 return lpx_get_obj_coef(lp, i);
617 virtual void _setObjCoef(int i, double obj_coef) {
618 lpx_set_obj_coef(lp, i, obj_coef);
622 void solveSimplex() { lpx_simplex(lp); }
624 void solvePrimalSimplex() { lpx_simplex(lp); }
626 void solveDualSimplex() { lpx_simplex(lp); }
629 virtual double _getPrimal(int i) {
630 return lpx_get_col_prim(lp, i);
634 double getObjVal() { return lpx_get_obj_val(lp); }
636 int rowNum() const { return lpx_get_num_rows(lp); }
638 int colNum() const { return lpx_get_num_cols(lp); }
640 int warmUp() { return lpx_warm_up(lp); }
642 void printWarmUpStatus(int i) {
644 case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
645 case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;
646 case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
647 case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
651 int getPrimalStatus() { return lpx_get_prim_stat(lp); }
653 void printPrimalStatus(int i) {
655 case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
656 case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;
657 case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
658 case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
662 int getDualStatus() { return lpx_get_dual_stat(lp); }
664 void printDualStatus(int i) {
666 case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
667 case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;
668 case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
669 case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
672 /// Returns the status of the slack variable assigned to row \c row_it.
673 int getRowStat(const RowIt& row_it) {
674 return lpx_get_row_stat(lp, row_iter_map[row_it]);
677 void printRowStatus(int i) {
679 case LPX_BS: cout << "LPX_BS" << endl; break;
680 case LPX_NL: cout << "LPX_NL" << endl; break;
681 case LPX_NU: cout << "LPX_NU" << endl; break;
682 case LPX_NF: cout << "LPX_NF" << endl; break;
683 case LPX_NS: cout << "LPX_NS" << endl; break;
686 /// Returns the status of the variable assigned to column \c col_it.
687 int getColStat(const ColIt& col_it) {
688 return lpx_get_col_stat(lp, col_iter_map[col_it]);
691 void printColStatus(int i) {
693 case LPX_BS: cout << "LPX_BS" << endl; break;
694 case LPX_NL: cout << "LPX_NL" << endl; break;
695 case LPX_NU: cout << "LPX_NU" << endl; break;
696 case LPX_NF: cout << "LPX_NF" << endl; break;
697 case LPX_NS: cout << "LPX_NS" << endl; break;
706 #endif //LEMON_LP_SOLVER_WRAPPER_H