2 #ifndef LEMON_LP_SOLVER_WRAPPER_H
3 #define LEMON_LP_SOLVER_WRAPPER_H
7 ///\brief Dijkstra algorithm.
27 //#include <sage_graph.h>
28 //#include <lemon/list_graph.h>
29 //#include <lemon/graph_wrapper.h>
30 #include <lemon/invalid.h>
31 #include <expression.h>
32 //#include <bfs_dfs.h>
34 //#include <lemon/max_flow.h>
35 //#include <augmenting_flow.h>
36 //#include <iter_map.h>
47 /// \brief A partitioned vector with iterable classes.
49 /// This class implements a container in which the data is stored in an
50 /// stl vector, the range is partitioned into sets and each set is
51 /// doubly linked in a list.
52 /// That is, each class is iterable by lemon iterators, and any member of
53 /// the vector can bo moved to an other class.
55 class IterablePartition {
59 int prev; //invalid az -1
62 std::vector<Node> nodes;
67 std::vector<Tip> tips;
69 /// The classes are indexed by integers from \c 0 to \c classNum()-1.
70 int classNum() const { return tips.size(); }
71 /// This lemon style iterator iterates through a class.
73 /// Constructor. The number of classes is to be given which is fixed
74 /// over the life of the container.
75 /// The partition classes are indexed from 0 to class_num-1.
76 IterablePartition(int class_num) {
77 for (int i=0; i<class_num; ++i) {
84 void befuz(ClassIt it, int class_id) {
85 if (tips[class_id].first==-1) {
86 if (tips[class_id].last==-1) {
87 nodes[it.i].prev=nodes[it.i].next=-1;
88 tips[class_id].first=tips[class_id].last=it.i;
91 nodes[it.i].prev=tips[class_id].last;
93 nodes[tips[class_id].last].next=it.i;
94 tips[class_id].last=it.i;
97 void kifuz(ClassIt it, int class_id) {
98 if (tips[class_id].first==it.i) {
99 if (tips[class_id].last==it.i) {
100 tips[class_id].first=tips[class_id].last=-1;
102 tips[class_id].first=nodes[it.i].next;
103 nodes[nodes[it.i].next].prev=-1;
106 if (tips[class_id].last==it.i) {
107 tips[class_id].last=nodes[it.i].prev;
108 nodes[nodes[it.i].prev].next=-1;
110 nodes[nodes[it.i].next].prev=nodes[it.i].prev;
111 nodes[nodes[it.i].prev].next=nodes[it.i].next;
116 /// A new element with data \c t is pushed into the vector and into class
118 ClassIt push_back(const T& t, int class_id) {
122 int i=nodes.size()-1;
126 /// A member is moved to an other class.
127 void set(ClassIt it, int old_class_id, int new_class_id) {
128 kifuz(it.i, old_class_id);
129 befuz(it.i, new_class_id);
131 /// Returns the data pointed by \c it.
132 T& operator[](ClassIt it) { return nodes[it.i].data; }
133 /// Returns the data pointed by \c it.
134 const T& operator[](ClassIt it) const { return nodes[it.i].data; }
137 friend class IterablePartition;
141 /// Default constructor.
143 /// This constructor constructs an iterator which points
144 /// to the member of th container indexed by the integer _i.
145 ClassIt(const int& _i) : i(_i) { }
146 /// Invalid constructor.
147 ClassIt(const Invalid&) : i(-1) { }
148 friend bool operator<(const ClassIt& x, const ClassIt& y);
149 friend std::ostream& operator<<(std::ostream& os,
152 friend bool operator<(const ClassIt& x, const ClassIt& y) {
155 friend std::ostream& operator<<(std::ostream& os,
160 /// First member of class \c class_id.
161 ClassIt& first(ClassIt& it, int class_id) const {
162 it.i=tips[class_id].first;
166 ClassIt& next(ClassIt& it) const {
167 it.i=nodes[it.i].next;
170 /// True iff the iterator is valid.
171 bool valid(const ClassIt& it) const { return it.i!=-1; }
177 \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
178 \todo LEKERDEZESEK!!!
179 \todo DOKSI!!!! Doxygen group!!!
182 template <typename _Value>
186 typedef _Value Value;
188 typedef IterablePartition<int>::ClassIt RowIt;
190 typedef IterablePartition<int>::ClassIt ColIt;
193 IterablePartition<int> row_iter_map;
195 IterablePartition<int> col_iter_map;
197 const int VALID_CLASS;
199 const int INVALID_CLASS;
201 static const _Value INF;
204 LPSolverBase() : row_iter_map(2),
206 VALID_CLASS(0), INVALID_CLASS(1) { }
208 virtual ~LPSolverBase() { }
210 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
214 virtual void setMinimize() = 0;
216 virtual void setMaximize() = 0;
218 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
222 virtual int _addRow() = 0;
224 virtual int _addCol() = 0;
226 virtual void _setRowCoeffs(int i,
227 const std::vector<std::pair<int, _Value> >& coeffs) = 0;
229 virtual void _setColCoeffs(int i,
230 const std::vector<std::pair<int, _Value> >& coeffs) = 0;
232 virtual void _eraseCol(int i) = 0;
234 virtual void _eraseRow(int i) = 0;
237 enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
240 virtual void _setColBounds(int i, Bound bound,
241 _Value lo, _Value up) = 0;
243 virtual void _setRowBounds(int i, Bound bound,
244 _Value lo, _Value up) = 0;
246 virtual void _setObjCoef(int i, _Value obj_coef) = 0;
248 virtual _Value _getObjCoef(int i) = 0;
250 //LOW LEVEL, SOLUTION RETRIEVING FUNCTIONS
253 virtual _Value _getPrimal(int i) = 0;
255 //HIGH LEVEL INTERFACE, MATRIX MANIPULATING FUNTIONS
262 row_iter_map.first(row_it, INVALID_CLASS);
263 if (row_iter_map.valid(row_it)) { //van hasznalhato hely
264 row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
265 row_iter_map[row_it]=i;
266 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
267 row_it=row_iter_map.push_back(i, VALID_CLASS);
275 col_iter_map.first(col_it, INVALID_CLASS);
276 if (col_iter_map.valid(col_it)) { //van hasznalhato hely
277 col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
278 col_iter_map[col_it]=i;
279 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
280 col_it=col_iter_map.push_back(i, VALID_CLASS);
285 template <typename Begin, typename End>
286 void setRowCoeffs(RowIt row_it, Begin begin, End end) {
287 std::vector<std::pair<int, double> > coeffs;
288 for ( ; begin!=end; ++begin) {
289 coeffs.push_back(std::
290 make_pair(col_iter_map[begin->first], begin->second));
292 _setRowCoeffs(row_iter_map[row_it], coeffs);
295 template <typename Begin, typename End>
296 void setColCoeffs(ColIt col_it, Begin begin, End end) {
297 std::vector<std::pair<int, double> > coeffs;
298 for ( ; begin!=end; ++begin) {
299 coeffs.push_back(std::
300 make_pair(row_iter_map[begin->first], begin->second));
302 _setColCoeffs(col_iter_map[col_it], coeffs);
305 void eraseCol(const ColIt& col_it) {
306 col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
308 cols[1]=col_iter_map[col_it];
310 col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
312 for (col_iter_map.first(it, VALID_CLASS);
313 col_iter_map.valid(it); col_iter_map.next(it)) {
314 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
318 void eraseRow(const RowIt& row_it) {
319 row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
321 rows[1]=row_iter_map[row_it];
323 row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
325 for (row_iter_map.first(it, VALID_CLASS);
326 row_iter_map.valid(it); row_iter_map.next(it)) {
327 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
331 void setColBounds(const ColIt& col_it, Bound bound,
332 _Value lo, _Value up) {
333 _setColBounds(col_iter_map[col_it], bound, lo, up);
336 void setRowBounds(const RowIt& row_it, Bound bound,
337 _Value lo, _Value up) {
338 _setRowBounds(row_iter_map[row_it], bound, lo, up);
341 void setObjCoef(const ColIt& col_it, _Value obj_coef) {
342 _setObjCoef(col_iter_map[col_it], obj_coef);
345 _Value getObjCoef(const ColIt& col_it) {
346 return _getObjCoef(col_iter_map[col_it]);
349 //MOST HIGH LEVEL, USER FRIEND FUNCTIONS
352 typedef Expr<ColIt, _Value> Expression;
354 typedef Expr<RowIt, _Value> DualExpression;
356 void setRowCoeffs(RowIt row_it, const Expression& expr) {
357 std::vector<std::pair<int, _Value> > row_coeffs;
358 for(typename Expression::Data::const_iterator i=expr.data.begin();
359 i!=expr.data.end(); ++i) {
360 row_coeffs.push_back(std::make_pair
361 (col_iter_map[(*i).first], (*i).second));
363 _setRowCoeffs(row_iter_map[row_it], row_coeffs);
366 void setColCoeffs(ColIt col_it, const DualExpression& expr) {
367 std::vector<std::pair<int, _Value> > col_coeffs;
368 for(typename DualExpression::Data::const_iterator i=expr.data.begin();
369 i!=expr.data.end(); ++i) {
370 col_coeffs.push_back(std::make_pair
371 (row_iter_map[(*i).first], (*i).second));
373 _setColCoeffs(col_iter_map[col_it], col_coeffs);
376 void setObjCoeffs(const Expression& expr) {
377 for(typename Expression::Data::const_iterator i=expr.data.begin();
378 i!=expr.data.end(); ++i) {
379 setObjCoef((*i).first, (*i).second);
385 virtual void solveSimplex() = 0;
387 virtual void solvePrimalSimplex() = 0;
389 virtual void solveDualSimplex() = 0;
392 //HIGH LEVEL, SOLUTION RETRIEVING FUNCTIONS
395 _Value getPrimal(const ColIt& col_it) {
396 return _getPrimal(col_iter_map[col_it]);
399 virtual _Value getObjVal() = 0;
404 virtual int rowNum() const = 0;
406 virtual int colNum() const = 0;
408 virtual int warmUp() = 0;
410 virtual void printWarmUpStatus(int i) = 0;
412 virtual int getPrimalStatus() = 0;
414 virtual void printPrimalStatus(int i) = 0;
416 virtual int getDualStatus() = 0;
418 virtual void printDualStatus(int i) = 0;
419 /// Returns the status of the slack variable assigned to row \c row_it.
420 virtual int getRowStat(const RowIt& row_it) = 0;
422 virtual void printRowStatus(int i) = 0;
423 /// Returns the status of the variable assigned to column \c col_it.
424 virtual int getColStat(const ColIt& col_it) = 0;
426 virtual void printColStatus(int i) = 0;
429 template <typename _Value>
430 const _Value LPSolverBase<_Value>::INF=std::numeric_limits<_Value>::infinity();
433 /// \brief Wrappers for LP solvers
435 /// This class implements a lemon wrapper for glpk.
436 /// Later other LP-solvers will be wrapped into lemon.
437 /// The aim of this class is to give a general surface to different
438 /// solvers, i.e. it makes possible to write algorithms using LP's,
439 /// in which the solver can be changed to an other one easily.
440 class LPGLPK : public LPSolverBase<double> {
442 typedef LPSolverBase<double> Parent;
451 lp(lpx_create_prob()) {
452 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
459 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
463 lpx_set_obj_dir(lp, LPX_MIN);
467 lpx_set_obj_dir(lp, LPX_MAX);
470 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
475 return lpx_add_cols(lp, 1);
479 return lpx_add_rows(lp, 1);
482 virtual void _setRowCoeffs(int i,
483 const std::vector<std::pair<int, double> >& coeffs) {
484 int mem_length=1+colNum();
485 int* indices = new int[mem_length];
486 double* doubles = new double[mem_length];
488 for (std::vector<std::pair<int, double> >::
489 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
491 indices[length]=it->first;
492 doubles[length]=it->second;
493 // std::cout << " " << indices[length] << " "
494 // << doubles[length] << std::endl;
496 // std::cout << i << " " << length << std::endl;
497 lpx_set_mat_row(lp, i, length, indices, doubles);
502 virtual void _setColCoeffs(int i,
503 const std::vector<std::pair<int, double> >& coeffs) {
504 int mem_length=1+rowNum();
505 int* indices = new int[mem_length];
506 double* doubles = new double[mem_length];
508 for (std::vector<std::pair<int, double> >::
509 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
511 indices[length]=it->first;
512 doubles[length]=it->second;
514 lpx_set_mat_col(lp, i, length, indices, doubles);
519 virtual void _eraseCol(int i) {
522 lpx_del_cols(lp, 1, cols);
524 virtual void _eraseRow(int i) {
527 lpx_del_rows(lp, 1, rows);
529 virtual void _setColBounds(int i, Bound bound,
530 double lo, double up) {
533 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
536 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
539 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
542 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
545 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
549 virtual void _setRowBounds(int i, Bound bound,
550 double lo, double up) {
553 lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
556 lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
559 lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
562 lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
565 lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
571 virtual double _getObjCoef(int i) {
572 return lpx_get_obj_coef(lp, i);
575 virtual void _setObjCoef(int i, double obj_coef) {
576 lpx_set_obj_coef(lp, i, obj_coef);
580 void solveSimplex() { lpx_simplex(lp); }
582 void solvePrimalSimplex() { lpx_simplex(lp); }
584 void solveDualSimplex() { lpx_simplex(lp); }
587 virtual double _getPrimal(int i) {
588 return lpx_get_col_prim(lp, i);
592 double getObjVal() { return lpx_get_obj_val(lp); }
594 int rowNum() const { return lpx_get_num_rows(lp); }
596 int colNum() const { return lpx_get_num_cols(lp); }
598 int warmUp() { return lpx_warm_up(lp); }
600 void printWarmUpStatus(int i) {
602 case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
603 case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;
604 case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
605 case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
609 int getPrimalStatus() { return lpx_get_prim_stat(lp); }
611 void printPrimalStatus(int i) {
613 case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
614 case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;
615 case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
616 case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
620 int getDualStatus() { return lpx_get_dual_stat(lp); }
622 void printDualStatus(int i) {
624 case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
625 case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;
626 case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
627 case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
630 /// Returns the status of the slack variable assigned to row \c row_it.
631 int getRowStat(const RowIt& row_it) {
632 return lpx_get_row_stat(lp, row_iter_map[row_it]);
635 void printRowStatus(int i) {
637 case LPX_BS: cout << "LPX_BS" << endl; break;
638 case LPX_NL: cout << "LPX_NL" << endl; break;
639 case LPX_NU: cout << "LPX_NU" << endl; break;
640 case LPX_NF: cout << "LPX_NF" << endl; break;
641 case LPX_NS: cout << "LPX_NS" << endl; break;
644 /// Returns the status of the variable assigned to column \c col_it.
645 int getColStat(const ColIt& col_it) {
646 return lpx_get_col_stat(lp, col_iter_map[col_it]);
649 void printColStatus(int i) {
651 case LPX_BS: cout << "LPX_BS" << endl; break;
652 case LPX_NL: cout << "LPX_NL" << endl; break;
653 case LPX_NU: cout << "LPX_NU" << endl; break;
654 case LPX_NF: cout << "LPX_NF" << endl; break;
655 case LPX_NS: cout << "LPX_NS" << endl; break;
664 #endif //LEMON_LP_SOLVER_WRAPPER_H