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>
44 /// \brief A partitioned vector with iterable classes.
46 /// This class implements a container in which the data is stored in an
47 /// stl vector, the range is partitioned into sets and each set is
48 /// doubly linked in a list.
49 /// That is, each class is iterable by lemon iterators, and any member of
50 /// the vector can bo moved to an other class.
52 class IterablePartition {
56 int prev; //invalid az -1
59 std::vector<Node> nodes;
64 std::vector<Tip> tips;
66 /// The classes are indexed by integers from \c 0 to \c classNum()-1.
67 int classNum() const { return tips.size(); }
68 /// This lemon style iterator iterates through a class.
70 /// Constructor. The number of classes is to be given which is fixed
71 /// over the life of the container.
72 /// The partition classes are indexed from 0 to class_num-1.
73 IterablePartition(int class_num) {
74 for (int i=0; i<class_num; ++i) {
81 void befuz(ClassIt it, int class_id) {
82 if (tips[class_id].first==-1) {
83 if (tips[class_id].last==-1) {
84 nodes[it.i].prev=nodes[it.i].next=-1;
85 tips[class_id].first=tips[class_id].last=it.i;
88 nodes[it.i].prev=tips[class_id].last;
90 nodes[tips[class_id].last].next=it.i;
91 tips[class_id].last=it.i;
94 void kifuz(ClassIt it, int class_id) {
95 if (tips[class_id].first==it.i) {
96 if (tips[class_id].last==it.i) {
97 tips[class_id].first=tips[class_id].last=-1;
99 tips[class_id].first=nodes[it.i].next;
100 nodes[nodes[it.i].next].prev=-1;
103 if (tips[class_id].last==it.i) {
104 tips[class_id].last=nodes[it.i].prev;
105 nodes[nodes[it.i].prev].next=-1;
107 nodes[nodes[it.i].next].prev=nodes[it.i].prev;
108 nodes[nodes[it.i].prev].next=nodes[it.i].next;
113 /// A new element with data \c t is pushed into the vector and into class
115 ClassIt push_back(const T& t, int class_id) {
119 int i=nodes.size()-1;
123 /// A member is moved to an other class.
124 void set(ClassIt it, int old_class_id, int new_class_id) {
125 kifuz(it.i, old_class_id);
126 befuz(it.i, new_class_id);
128 /// Returns the data pointed by \c it.
129 T& operator[](ClassIt it) { return nodes[it.i].data; }
130 /// Returns the data pointed by \c it.
131 const T& operator[](ClassIt it) const { return nodes[it.i].data; }
134 friend class IterablePartition;
138 /// Default constructor.
140 /// This constructor constructs an iterator which points
141 /// to the member of th container indexed by the integer _i.
142 ClassIt(const int& _i) : i(_i) { }
143 /// Invalid constructor.
144 ClassIt(const Invalid&) : i(-1) { }
146 /// First member of class \c class_id.
147 ClassIt& first(ClassIt& it, int class_id) const {
148 it.i=tips[class_id].first;
152 ClassIt& next(ClassIt& it) const {
153 it.i=nodes[it.i].next;
156 /// True iff the iterator is valid.
157 bool valid(const ClassIt& it) const { return it.i!=-1; }
162 template <typename _Value>
166 typedef _Value Value;
168 typedef IterablePartition<int>::ClassIt RowIt;
170 typedef IterablePartition<int>::ClassIt ColIt;
173 IterablePartition<int> row_iter_map;
175 IterablePartition<int> col_iter_map;
177 const int VALID_CLASS;
179 const int INVALID_CLASS;
182 LPSolverBase() : row_iter_map(2),
184 VALID_CLASS(0), INVALID_CLASS(1) { }
186 virtual ~LPSolverBase() { }
188 virtual void setMinimize() = 0;
190 virtual void setMaximize() = 0;
193 virtual int _addRow() = 0;
195 virtual int _addCol() = 0;
201 row_iter_map.first(row_it, INVALID_CLASS);
202 if (row_iter_map.valid(row_it)) { //van hasznalhato hely
203 row_iter_map.set(row_it, INVALID_CLASS, VALID_CLASS);
204 row_iter_map[row_it]=i;
205 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
206 row_it=row_iter_map.push_back(i, VALID_CLASS);
214 col_iter_map.first(col_it, INVALID_CLASS);
215 if (col_iter_map.valid(col_it)) { //van hasznalhato hely
216 col_iter_map.set(col_it, INVALID_CLASS, VALID_CLASS);
217 col_iter_map[col_it]=i;
218 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
219 col_it=col_iter_map.push_back(i, VALID_CLASS);
224 virtual void setRowCoeffs(int i,
225 std::vector<std::pair<int, double> > coeffs) = 0;
227 virtual void setColCoeffs(int i,
228 std::vector<std::pair<int, double> > coeffs) = 0;
230 template <typename Begin, typename End>
231 void setRowCoeffs(RowIt row_it, Begin begin, End end) {
232 std::vector<std::pair<int, double> > coeffs;
233 for ( ; begin!=end; ++begin) {
234 coeffs.push_back(std::
235 make_pair(col_iter_map[begin->first], begin->second));
237 setRowCoeffs(row_iter_map[row_it], coeffs);
240 template <typename Begin, typename End>
241 void setColCoeffs(ColIt col_it, Begin begin, End end) {
242 std::vector<std::pair<int, double> > coeffs;
243 for ( ; begin!=end; ++begin) {
244 coeffs.push_back(std::
245 make_pair(row_iter_map[begin->first], begin->second));
247 setColCoeffs(col_iter_map[col_it], coeffs);
249 /// temporally, glpk style indexing
250 //virtual void setRowCoeffs(RowIt row_it, int num,
251 // int* indices, _Value* doubles) = 0;
252 //pair<RowIt, _Value>-bol kell megadni egy std range-et
254 // virtual void seColCoeffs(int i,
255 // std::vector<std::pair<int, double> > coeffs) = 0;
257 // template <typename Begin, typename End>
258 // void setRowCoeffs(RowIt row_it, Begin begin, End end) {
259 // int mem_length=1+colNum();
260 // int* indices = new int[mem_length];
261 // _Value* doubles = new _Value[mem_length];
263 // for ( ; begin!=end; ++begin) {
265 // indices[length]=col_iter_map[begin->first];
266 // doubles[length]=begin->second;
268 // setRowCoeffs(row_it, length, indices, doubles);
269 // delete [] indices;
270 // delete [] doubles;
272 /// temporally, glpk style indexing
273 //virtual void setColCoeffs(ColIt col_it, int num,
274 // int* indices, _Value* doubles) = 0;
275 //pair<ColIt, _Value>-bol kell megadni egy std range-et
277 // template <typename Begin, typename End>
278 // void setColCoeffs(ColIt col_it, Begin begin, End end) {
279 // int mem_length=1+rowNum();
280 // int* indices = new int[mem_length];
281 // _Value* doubles = new _Value[mem_length];
283 // for ( ; begin!=end; ++begin) {
285 // indices[length]=row_iter_map[begin->first];
286 // doubles[length]=begin->second;
288 // setColCoeffs(col_it, length, indices, doubles);
289 // delete [] indices;
290 // delete [] doubles;
294 virtual void _eraseCol(int i) = 0;
296 virtual void _eraseRow(int i) = 0;
299 void eraseCol(const ColIt& col_it) {
300 col_iter_map.set(col_it, VALID_CLASS, INVALID_CLASS);
302 cols[1]=col_iter_map[col_it];
304 col_iter_map[col_it]=0; //glpk specifikus, de kell ez??
306 for (col_iter_map.first(it, VALID_CLASS);
307 col_iter_map.valid(it); col_iter_map.next(it)) {
308 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
312 void eraseRow(const RowIt& row_it) {
313 row_iter_map.set(row_it, VALID_CLASS, INVALID_CLASS);
315 rows[1]=row_iter_map[row_it];
317 row_iter_map[row_it]=0; //glpk specifikus, de kell ez??
319 for (row_iter_map.first(it, VALID_CLASS);
320 row_iter_map.valid(it); row_iter_map.next(it)) {
321 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
325 virtual void setColBounds(const ColIt& col_it, int bound_type,
326 _Value lo, _Value up) =0;
328 virtual _Value getObjCoef(const ColIt& col_it) = 0;
330 virtual void setRowBounds(const RowIt& row_it, int bound_type,
331 _Value lo, _Value up) = 0;
333 virtual void setObjCoef(const ColIt& col_it, _Value obj_coef) = 0;
335 virtual void solveSimplex() = 0;
337 virtual void solvePrimalSimplex() = 0;
339 virtual void solveDualSimplex() = 0;
341 virtual _Value getPrimal(const ColIt& col_it) = 0;
343 virtual _Value getObjVal() = 0;
345 virtual int rowNum() const = 0;
347 virtual int colNum() const = 0;
349 virtual int warmUp() = 0;
351 virtual void printWarmUpStatus(int i) = 0;
353 virtual int getPrimalStatus() = 0;
355 virtual void printPrimalStatus(int i) = 0;
357 virtual int getDualStatus() = 0;
359 virtual void printDualStatus(int i) = 0;
360 /// Returns the status of the slack variable assigned to row \c row_it.
361 virtual int getRowStat(const RowIt& row_it) = 0;
363 virtual void printRowStatus(int i) = 0;
364 /// Returns the status of the variable assigned to column \c col_it.
365 virtual int getColStat(const ColIt& col_it) = 0;
367 virtual void printColStatus(int i) = 0;
371 /// \brief Wrappers for LP solvers
373 /// This class implements a lemon wrapper for glpk.
374 /// Later other LP-solvers will be wrapped into lemon.
375 /// The aim of this class is to give a general surface to different
376 /// solvers, i.e. it makes possible to write algorithms using LP's,
377 /// in which the solver can be changed to an other one easily.
378 class LPSolverWrapper : public LPSolverBase<double> {
380 typedef LPSolverBase<double> Parent;
388 LPSolverWrapper() : Parent(),
389 lp(lpx_create_prob()) {
390 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
398 lpx_set_obj_dir(lp, LPX_MIN);
402 lpx_set_obj_dir(lp, LPX_MAX);
407 return lpx_add_cols(lp, 1);
411 return lpx_add_rows(lp, 1);
414 using Parent::setRowCoeffs;
416 virtual void setRowCoeffs(int i,
417 std::vector<std::pair<int, double> > coeffs) {
418 int mem_length=1+colNum();
419 int* indices = new int[mem_length];
420 double* doubles = new double[mem_length];
422 for (std::vector<std::pair<int, double> >::
423 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
425 indices[length]=it->first;
426 doubles[length]=it->second;
427 std::cout << " " << indices[length] << " "
428 << doubles[length] << std::endl;
430 std::cout << i << " " << length << std::endl;
431 lpx_set_mat_row(lp, i, length, indices, doubles);
436 virtual void setColCoeffs(int i,
437 std::vector<std::pair<int, double> > coeffs) {
438 int mem_length=1+rowNum();
439 int* indices = new int[mem_length];
440 double* doubles = new double[mem_length];
442 for (std::vector<std::pair<int, double> >::
443 const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
445 indices[length]=it->first;
446 doubles[length]=it->second;
448 lpx_set_mat_col(lp, i, length, indices, doubles);
453 // /// temporally, glpk style indexing
454 // virtual void setRowCoeffs(RowIt row_it, int num,
455 // int* indices, _Value* doubles) = 0;
456 // //pair<RowIt, _Value>-bol kell megadni egy std range-et
458 // template <typename Begin, typename End>
459 // void setRowCoeffs(RowIt row_it, Begin begin, End end) {
460 // int mem_length=1+colNum();
461 // int* indices = new int[mem_length];
462 // _Value* doubles = new _Value[mem_length];
464 // for ( ; begin!=end; ++begin) {
466 // indices[length]=col_iter_map[begin->first];
467 // doubles[length]=begin->second;
469 // setRowCoeffs(row_it, length, indices, doubles);
470 // delete [] indices;
471 // delete [] doubles;
473 // void setRowCoeffs(RowIt row_it, int length,
474 // int* indices, double* doubles) {
475 // lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles);
477 // using Parent::setColCoeffs;
478 // void setColCoeffs(ColIt col_it, int length,
479 // int* indices, double* doubles) {
480 // lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles);
482 // //pair<RowIt, double>-bol kell megadni egy std range-et
484 // template <typename Begin, typename End>
485 // void setColCoeffs(const ColIt& col_it,
486 // Begin begin, End end) {
487 // int mem_length=1+lpx_get_num_rows(lp);
488 // int* indices = new int[mem_length];
489 // double* doubles = new double[mem_length];
491 // for ( ; begin!=end; ++begin) {
493 // indices[length]=row_iter_map[begin->first];
494 // doubles[length]=begin->second;
496 // lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles);
497 // delete [] indices;
498 // delete [] doubles;
500 // //pair<ColIt, double>-bol kell megadni egy std range-et
502 // template <typename Begin, typename End>
503 // void setRowCoeffs(const RowIt& row_it,
504 // Begin begin, End end) {
505 // int mem_length=1+lpx_get_num_cols(lp);
506 // int* indices = new int[mem_length];
507 // double* doubles = new double[mem_length];
509 // for ( ; begin!=end; ++begin) {
511 // indices[length]=col_iter_map[begin->first];
512 // doubles[length]=begin->second;
514 // lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles);
515 // delete [] indices;
516 // delete [] doubles;
520 virtual void _eraseCol(int i) {
523 lpx_del_cols(lp, 1, cols);
525 virtual void _eraseRow(int i) {
528 lpx_del_rows(lp, 1, rows);
532 void setColBounds(const ColIt& col_it, int bound_type,
533 double lo, double up) {
534 lpx_set_col_bnds(lp, col_iter_map[col_it], bound_type, lo, up);
537 double getObjCoef(const ColIt& col_it) {
538 return lpx_get_obj_coef(lp, col_iter_map[col_it]);
541 void setRowBounds(const RowIt& row_it, int bound_type,
542 double lo, double up) {
543 lpx_set_row_bnds(lp, row_iter_map[row_it], bound_type, lo, up);
546 void setObjCoef(const ColIt& col_it, double obj_coef) {
547 lpx_set_obj_coef(lp, col_iter_map[col_it], obj_coef);
550 void solveSimplex() { lpx_simplex(lp); }
552 void solvePrimalSimplex() { lpx_simplex(lp); }
554 void solveDualSimplex() { lpx_simplex(lp); }
556 double getPrimal(const ColIt& col_it) {
557 return lpx_get_col_prim(lp, col_iter_map[col_it]);
560 double getObjVal() { return lpx_get_obj_val(lp); }
562 int rowNum() const { return lpx_get_num_rows(lp); }
564 int colNum() const { return lpx_get_num_cols(lp); }
566 int warmUp() { return lpx_warm_up(lp); }
568 void printWarmUpStatus(int i) {
570 case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
571 case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;
572 case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
573 case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
577 int getPrimalStatus() { return lpx_get_prim_stat(lp); }
579 void printPrimalStatus(int i) {
581 case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
582 case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;
583 case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
584 case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
588 int getDualStatus() { return lpx_get_dual_stat(lp); }
590 void printDualStatus(int i) {
592 case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
593 case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;
594 case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
595 case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
598 /// Returns the status of the slack variable assigned to row \c row_it.
599 int getRowStat(const RowIt& row_it) {
600 return lpx_get_row_stat(lp, row_iter_map[row_it]);
603 void printRowStatus(int i) {
605 case LPX_BS: cout << "LPX_BS" << endl; break;
606 case LPX_NL: cout << "LPX_NL" << endl; break;
607 case LPX_NU: cout << "LPX_NU" << endl; break;
608 case LPX_NF: cout << "LPX_NF" << endl; break;
609 case LPX_NS: cout << "LPX_NS" << endl; break;
612 /// Returns the status of the variable assigned to column \c col_it.
613 int getColStat(const ColIt& col_it) {
614 return lpx_get_col_stat(lp, col_iter_map[col_it]);
617 void printColStatus(int i) {
619 case LPX_BS: cout << "LPX_BS" << endl; break;
620 case LPX_NL: cout << "LPX_NL" << endl; break;
621 case LPX_NU: cout << "LPX_NU" << endl; break;
622 case LPX_NF: cout << "LPX_NF" << endl; break;
623 case LPX_NS: cout << "LPX_NS" << endl; break;
632 #endif //LEMON_LP_SOLVER_WRAPPER_H