2 #ifndef LEMON_LP_SOLVER_WRAPPER_H
3 #define LEMON_LP_SOLVER_WRAPPER_H
7 ///\brief Dijkstra algorithm.
24 //#include <sage_graph.h>
25 //#include <lemon/list_graph.h>
26 //#include <lemon/graph_wrapper.h>
27 #include <lemon/invalid.h>
28 //#include <bfs_dfs.h>
30 //#include <lemon/max_flow.h>
31 //#include <augmenting_flow.h>
32 //#include <iter_map.h>
43 /// \brief A partitioned vector with iterable classes.
45 /// This class implements a container in which the data is stored in an
46 /// stl vector, the range is partitioned into sets and each set is
47 /// doubly linked in a list.
48 /// That is, each class is iterable by lemon iterators, and any member of
49 /// the vector can bo moved to an other class.
51 class IterablePartition {
55 int prev; //invalid az -1
58 std::vector<Node> nodes;
63 std::vector<Tip> tips;
65 /// The classes are indexed by integers from \c 0 to \c classNum()-1.
66 int classNum() const { return tips.size(); }
67 /// This lemon style iterator iterates through a class.
69 /// Constructor. The number of classes is to be given which is fixed
70 /// over the life of the container.
71 /// The partition classes are indexed from 0 to class_num-1.
72 IterablePartition(int class_num) {
73 for (int i=0; i<class_num; ++i) {
80 void befuz(ClassIt it, int class_id) {
81 if (tips[class_id].first==-1) {
82 if (tips[class_id].last==-1) {
83 nodes[it.i].prev=nodes[it.i].next=-1;
84 tips[class_id].first=tips[class_id].last=it.i;
87 nodes[it.i].prev=tips[class_id].last;
89 nodes[tips[class_id].last].next=it.i;
90 tips[class_id].last=it.i;
93 void kifuz(ClassIt it, int class_id) {
94 if (tips[class_id].first==it.i) {
95 if (tips[class_id].last==it.i) {
96 tips[class_id].first=tips[class_id].last=-1;
98 tips[class_id].first=nodes[it.i].next;
99 nodes[nodes[it.i].next].prev=-1;
102 if (tips[class_id].last==it.i) {
103 tips[class_id].last=nodes[it.i].prev;
104 nodes[nodes[it.i].prev].next=-1;
106 nodes[nodes[it.i].next].prev=nodes[it.i].prev;
107 nodes[nodes[it.i].prev].next=nodes[it.i].next;
112 /// A new element with data \c t is pushed into the vector and into class
114 ClassIt push_back(const T& t, int class_id) {
118 int i=nodes.size()-1;
122 /// A member is moved to an other class.
123 void set(ClassIt it, int old_class_id, int new_class_id) {
124 kifuz(it.i, old_class_id);
125 befuz(it.i, new_class_id);
127 /// Returns the data pointed by \c it.
128 T& operator[](ClassIt it) { return nodes[it.i].data; }
129 /// Returns the data pointed by \c it.
130 const T& operator[](ClassIt it) const { return nodes[it.i].data; }
133 friend class IterablePartition;
137 /// Default constructor.
139 /// This constructor constructs an iterator which points
140 /// to the member of th container indexed by the integer _i.
141 ClassIt(const int& _i) : i(_i) { }
142 /// Invalid constructor.
143 ClassIt(const Invalid&) : i(-1) { }
145 /// First member of class \c class_id.
146 ClassIt& first(ClassIt& it, int class_id) const {
147 it.i=tips[class_id].first;
151 ClassIt& next(ClassIt& it) const {
152 it.i=nodes[it.i].next;
155 /// True iff the iterator is valid.
156 bool valid(const ClassIt& it) const { return it.i!=-1; }
161 template <typename _Value>
165 typedef _Value Value;
167 typedef IterablePartition<int>::ClassIt RowIt;
169 typedef IterablePartition<int>::ClassIt ColIt;
172 IterablePartition<int> row_iter_map;
174 IterablePartition<int> col_iter_map;
176 const int VALID_CLASS;
178 const int INVALID_CLASS;
181 LPSolverBase() : row_iter_map(2),
183 VALID_CLASS(0), INVALID_CLASS(1) { }
185 virtual ~LPSolverBase() { }
187 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
191 virtual void setMinimize() = 0;
193 virtual void setMaximize() = 0;
195 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
199 virtual int _addRow() = 0;
201 virtual int _addCol() = 0;
203 virtual void _setRowCoeffs(int i,
204 std::vector<std::pair<int, double> > coeffs) = 0;
206 virtual void _setColCoeffs(int i,
207 std::vector<std::pair<int, double> > coeffs) = 0;
209 virtual void _eraseCol(int i) = 0;
211 virtual void _eraseRow(int i) = 0;
214 enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
217 virtual void _setColBounds(int i, Bound bound,
218 _Value lo, _Value up) = 0;
220 virtual void _setRowBounds(int i, Bound bound,
221 _Value lo, _Value up) = 0;
223 virtual void _setObjCoef(int i, _Value obj_coef) = 0;
225 virtual _Value _getObjCoef(int i) = 0;
227 //LOW LEVEL, SOLUTION RETRIEVING FUNCTIONS
230 virtual _Value _getPrimal(int i) = 0;
232 //HIGH LEVEL INTERFACE, MATRIX MANIPULATING FUNTIONS
239 row_iter_map.first(row_it, INVALID_CLASS);
240 if (row_iter_map.valid(row_it)) { //van hasznalhato hely
241 row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
242 row_iter_map[row_it]=i;
243 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
244 row_it=row_iter_map.push_back(i, VALID_CLASS);
252 col_iter_map.first(col_it, INVALID_CLASS);
253 if (col_iter_map.valid(col_it)) { //van hasznalhato hely
254 col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
255 col_iter_map[col_it]=i;
256 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
257 col_it=col_iter_map.push_back(i, VALID_CLASS);
262 template <typename Begin, typename End>
263 void setRowCoeffs(RowIt row_it, Begin begin, End end) {
264 std::vector<std::pair<int, double> > coeffs;
265 for ( ; begin!=end; ++begin) {
266 coeffs.push_back(std::
267 make_pair(col_iter_map[begin->first], begin->second));
269 _setRowCoeffs(row_iter_map[row_it], coeffs);
272 template <typename Begin, typename End>
273 void setColCoeffs(ColIt col_it, Begin begin, End end) {
274 std::vector<std::pair<int, double> > coeffs;
275 for ( ; begin!=end; ++begin) {
276 coeffs.push_back(std::
277 make_pair(row_iter_map[begin->first], begin->second));
279 _setColCoeffs(col_iter_map[col_it], coeffs);
282 void eraseCol(const ColIt& col_it) {
283 col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
285 cols[1]=col_iter_map[col_it];
287 col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
289 for (col_iter_map.first(it, VALID_CLASS);
290 col_iter_map.valid(it); col_iter_map.next(it)) {
291 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
295 void eraseRow(const RowIt& row_it) {
296 row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
298 rows[1]=row_iter_map[row_it];
300 row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
302 for (row_iter_map.first(it, VALID_CLASS);
303 row_iter_map.valid(it); row_iter_map.next(it)) {
304 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
308 void setColBounds(const ColIt& col_it, Bound bound,
309 _Value lo, _Value up) {
310 _setColBounds(col_iter_map[col_it], bound, lo, up);
313 void setRowBounds(const RowIt& row_it, Bound bound,
314 _Value lo, _Value up) {
315 _setRowBounds(row_iter_map[row_it], bound, lo, up);
318 void setObjCoef(const ColIt& col_it, _Value obj_coef) {
319 _setObjCoef(col_iter_map[col_it], obj_coef);
322 _Value getObjCoef(const ColIt& col_it) {
323 return _getObjCoef(col_iter_map[col_it]);
329 virtual void solveSimplex() = 0;
331 virtual void solvePrimalSimplex() = 0;
333 virtual void solveDualSimplex() = 0;
336 //HIGH LEVEL, SOLUTION RETRIEVING FUNCTIONS
339 _Value getPrimal(const ColIt& col_it) {
340 return _getPrimal(col_iter_map[col_it]);
343 virtual _Value getObjVal() = 0;
348 virtual int rowNum() const = 0;
350 virtual int colNum() const = 0;
352 virtual int warmUp() = 0;
354 virtual void printWarmUpStatus(int i) = 0;
356 virtual int getPrimalStatus() = 0;
358 virtual void printPrimalStatus(int i) = 0;
360 virtual int getDualStatus() = 0;
362 virtual void printDualStatus(int i) = 0;
363 /// Returns the status of the slack variable assigned to row \c row_it.
364 virtual int getRowStat(const RowIt& row_it) = 0;
366 virtual void printRowStatus(int i) = 0;
367 /// Returns the status of the variable assigned to column \c col_it.
368 virtual int getColStat(const ColIt& col_it) = 0;
370 virtual void printColStatus(int i) = 0;
374 /// \brief Wrappers for LP solvers
376 /// This class implements a lemon wrapper for glpk.
377 /// Later other LP-solvers will be wrapped into lemon.
378 /// The aim of this class is to give a general surface to different
379 /// solvers, i.e. it makes possible to write algorithms using LP's,
380 /// in which the solver can be changed to an other one easily.
381 class LPGLPK : public LPSolverBase<double> {
383 typedef LPSolverBase<double> Parent;
392 lp(lpx_create_prob()) {
393 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
400 //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
404 lpx_set_obj_dir(lp, LPX_MIN);
408 lpx_set_obj_dir(lp, LPX_MAX);
411 //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
416 return lpx_add_cols(lp, 1);
420 return lpx_add_rows(lp, 1);
423 virtual void _setRowCoeffs(int i,
424 std::vector<std::pair<int, double> > coeffs) {
425 int mem_length=1+colNum();
426 int* indices = new int[mem_length];
427 double* doubles = new double[mem_length];
429 for (std::vector<std::pair<int, double> >::
430 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
432 indices[length]=it->first;
433 doubles[length]=it->second;
434 // std::cout << " " << indices[length] << " "
435 // << doubles[length] << std::endl;
437 // std::cout << i << " " << length << std::endl;
438 lpx_set_mat_row(lp, i, length, indices, doubles);
443 virtual void _setColCoeffs(int i,
444 std::vector<std::pair<int, double> > coeffs) {
445 int mem_length=1+rowNum();
446 int* indices = new int[mem_length];
447 double* doubles = new double[mem_length];
449 for (std::vector<std::pair<int, double> >::
450 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
452 indices[length]=it->first;
453 doubles[length]=it->second;
455 lpx_set_mat_col(lp, i, length, indices, doubles);
460 virtual void _eraseCol(int i) {
463 lpx_del_cols(lp, 1, cols);
465 virtual void _eraseRow(int i) {
468 lpx_del_rows(lp, 1, rows);
470 virtual void _setColBounds(int i, Bound bound,
471 double lo, double up) {
474 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
477 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
480 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
483 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
486 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
490 virtual void _setRowBounds(int i, Bound bound,
491 double lo, double up) {
494 lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
497 lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
500 lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
503 lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
506 lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
512 virtual double _getObjCoef(int i) {
513 return lpx_get_obj_coef(lp, i);
516 virtual void _setObjCoef(int i, double obj_coef) {
517 lpx_set_obj_coef(lp, i, obj_coef);
521 void solveSimplex() { lpx_simplex(lp); }
523 void solvePrimalSimplex() { lpx_simplex(lp); }
525 void solveDualSimplex() { lpx_simplex(lp); }
528 virtual double _getPrimal(int i) {
529 return lpx_get_col_prim(lp, i);
533 double getObjVal() { return lpx_get_obj_val(lp); }
535 int rowNum() const { return lpx_get_num_rows(lp); }
537 int colNum() const { return lpx_get_num_cols(lp); }
539 int warmUp() { return lpx_warm_up(lp); }
541 void printWarmUpStatus(int i) {
543 case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
544 case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;
545 case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
546 case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
550 int getPrimalStatus() { return lpx_get_prim_stat(lp); }
552 void printPrimalStatus(int i) {
554 case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
555 case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;
556 case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
557 case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
561 int getDualStatus() { return lpx_get_dual_stat(lp); }
563 void printDualStatus(int i) {
565 case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
566 case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;
567 case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
568 case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
571 /// Returns the status of the slack variable assigned to row \c row_it.
572 int getRowStat(const RowIt& row_it) {
573 return lpx_get_row_stat(lp, row_iter_map[row_it]);
576 void printRowStatus(int i) {
578 case LPX_BS: cout << "LPX_BS" << endl; break;
579 case LPX_NL: cout << "LPX_NL" << endl; break;
580 case LPX_NU: cout << "LPX_NU" << endl; break;
581 case LPX_NF: cout << "LPX_NF" << endl; break;
582 case LPX_NS: cout << "LPX_NS" << endl; break;
585 /// Returns the status of the variable assigned to column \c col_it.
586 int getColStat(const ColIt& col_it) {
587 return lpx_get_col_stat(lp, col_iter_map[col_it]);
590 void printColStatus(int i) {
592 case LPX_BS: cout << "LPX_BS" << endl; break;
593 case LPX_NL: cout << "LPX_NL" << endl; break;
594 case LPX_NU: cout << "LPX_NU" << endl; break;
595 case LPX_NF: cout << "LPX_NF" << endl; break;
596 case LPX_NS: cout << "LPX_NS" << endl; break;
605 #endif //LEMON_LP_SOLVER_WRAPPER_H