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; }
165 typedef IterablePartition<int>::ClassIt RowIt;
167 typedef IterablePartition<int>::ClassIt ColIt;
170 IterablePartition<int> row_iter_map;
172 IterablePartition<int> col_iter_map;
176 const int INVALID_ID;
179 LPSolverBase() : row_iter_map(2),
181 VALID_ID(0), INVALID_ID(1) { }
183 virtual ~LPSolverBase() { }
185 virtual void setMinimize() = 0;
187 virtual void setMaximize() = 0;
189 virtual RowIt addRow() = 0;
191 virtual ColIt addCol() = 0;
192 /// temporally, glpk style indexing
193 virtual void setRowCoeffs(RowIt row_it, int num,
194 int* indices, double* doubles) = 0;
195 //pair<RowIt, double>-bol kell megadni egy std range-et
197 template <typename Begin, typename End>
198 void setRowCoeffs(RowIt row_it, Begin begin, End end) {
199 int mem_length=1+colNum();
200 int* indices = new int[mem_length];
201 double* doubles = new double[mem_length];
203 for ( ; begin!=end; ++begin) {
205 indices[length]=col_iter_map[begin->first];
206 doubles[length]=begin->second;
208 setRowCoeffs(row_it, length, indices, doubles);
212 /// temporally, glpk style indexing
213 virtual void setColCoeffs(ColIt col_it, int num,
214 int* indices, double* doubles) = 0;
215 //pair<ColIt, double>-bol kell megadni egy std range-et
217 template <typename Begin, typename End>
218 void setColCoeffs(ColIt col_it, Begin begin, End end) {
219 int mem_length=1+rowNum();
220 int* indices = new int[mem_length];
221 double* doubles = new double[mem_length];
223 for ( ; begin!=end; ++begin) {
225 indices[length]=row_iter_map[begin->first];
226 doubles[length]=begin->second;
228 setColCoeffs(col_it, length, indices, doubles);
233 virtual void eraseCol(const ColIt& col_it) = 0;
235 virtual void eraseRow(const RowIt& row_it) = 0;
237 virtual void setColBounds(const ColIt& col_it, int bound_type,
238 double lo, double up) =0;
240 virtual double getObjCoef(const ColIt& col_it) = 0;
242 virtual void setRowBounds(const RowIt& row_it, int bound_type,
243 double lo, double up) = 0;
245 virtual void setObjCoef(const ColIt& col_it, double obj_coef) = 0;
247 virtual void solveSimplex() = 0;
249 virtual void solvePrimalSimplex() = 0;
251 virtual void solveDualSimplex() = 0;
253 virtual double getPrimal(const ColIt& col_it) = 0;
255 virtual double getObjVal() = 0;
257 virtual int rowNum() const = 0;
259 virtual int colNum() const = 0;
261 virtual int warmUp() = 0;
263 virtual void printWarmUpStatus(int i) = 0;
265 virtual int getPrimalStatus() = 0;
267 virtual void printPrimalStatus(int i) = 0;
269 virtual int getDualStatus() = 0;
271 virtual void printDualStatus(int i) = 0;
272 /// Returns the status of the slack variable assigned to row \c row_it.
273 virtual int getRowStat(const RowIt& row_it) = 0;
275 virtual void printRowStatus(int i) = 0;
276 /// Returns the status of the variable assigned to column \c col_it.
277 virtual int getColStat(const ColIt& col_it) = 0;
279 virtual void printColStatus(int i) = 0;
282 /// \brief Wrappers for LP solvers
284 /// This class implements a lemon wrapper for glpk.
285 /// Later other LP-solvers will be wrapped into lemon.
286 /// The aim of this class is to give a general surface to different
287 /// solvers, i.e. it makes possible to write algorithms using LP's,
288 /// in which the solver can be changed to an other one easily.
289 class LPSolverWrapper : public LPSolverBase {
291 typedef LPSolverBase Parent;
298 // Row(const Invalid&) : i(0) { }
299 // Row(const int& _i) : i(_i) { }
300 // operator int() const { return i; }
302 // class RowIt : public Row {
304 // RowIt(const Row& row) : Row(row) { }
312 // Col(const Invalid&) : i(0) { }
313 // Col(const int& _i) : i(_i) { }
314 // operator int() const { return i; }
316 // class ColIt : public Col {
317 // ColIt(const Col& col) : Col(col) { }
326 LPSolverWrapper() : LPSolverBase(),
327 lp(lpx_create_prob()) {
328 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
336 lpx_set_obj_dir(lp, LPX_MIN);
340 lpx_set_obj_dir(lp, LPX_MAX);
344 int i=lpx_add_cols(lp, 1);
346 col_iter_map.first(col_it, INVALID_ID);
347 if (col_iter_map.valid(col_it)) { //van hasznalhato hely
348 col_iter_map.set(col_it, INVALID_ID, VALID_ID);
349 col_iter_map[col_it]=i;
350 //col_id_to_lp_col_id[col_iter_map[col_it]]=i;
351 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
352 //col_id_to_lp_col_id.push_back(i);
353 //int j=col_id_to_lp_col_id.size()-1;
354 col_it=col_iter_map.push_back(i, VALID_ID);
356 // edge_index_map.set(e, i);
357 // lpx_set_col_bnds(lp, i, LPX_DB, 0.0, 1.0);
358 // lpx_set_obj_coef(lp, i, cost[e]);
363 int i=lpx_add_rows(lp, 1);
365 row_iter_map.first(row_it, INVALID_ID);
366 if (row_iter_map.valid(row_it)) { //van hasznalhato hely
367 row_iter_map.set(row_it, INVALID_ID, VALID_ID);
368 row_iter_map[row_it]=i;
369 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
370 row_it=row_iter_map.push_back(i, VALID_ID);
374 using Parent::setRowCoeffs;
375 void setRowCoeffs(RowIt row_it, int length,
376 int* indices, double* doubles) {
377 lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles);
379 using Parent::setColCoeffs;
380 void setColCoeffs(ColIt col_it, int length,
381 int* indices, double* doubles) {
382 lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles);
384 // //pair<RowIt, double>-bol kell megadni egy std range-et
386 // template <typename Begin, typename End>
387 // void setColCoeffs(const ColIt& col_it,
388 // Begin begin, End end) {
389 // int mem_length=1+lpx_get_num_rows(lp);
390 // int* indices = new int[mem_length];
391 // double* doubles = new double[mem_length];
393 // for ( ; begin!=end; ++begin) {
395 // indices[length]=row_iter_map[begin->first];
396 // doubles[length]=begin->second;
398 // lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles);
399 // delete [] indices;
400 // delete [] doubles;
402 // //pair<ColIt, double>-bol kell megadni egy std range-et
404 // template <typename Begin, typename End>
405 // void setRowCoeffs(const RowIt& row_it,
406 // Begin begin, End end) {
407 // int mem_length=1+lpx_get_num_cols(lp);
408 // int* indices = new int[mem_length];
409 // double* doubles = new double[mem_length];
411 // for ( ; begin!=end; ++begin) {
413 // indices[length]=col_iter_map[begin->first];
414 // doubles[length]=begin->second;
416 // lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles);
417 // delete [] indices;
418 // delete [] doubles;
421 void eraseCol(const ColIt& col_it) {
422 col_iter_map.set(col_it, VALID_ID, INVALID_ID);
424 cols[1]=col_iter_map[col_it];
425 lpx_del_cols(lp, 1, cols);
426 col_iter_map[col_it]=0; //glpk specifikus
428 for (col_iter_map.first(it, VALID_ID);
429 col_iter_map.valid(it); col_iter_map.next(it)) {
430 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
434 void eraseRow(const RowIt& row_it) {
435 row_iter_map.set(row_it, VALID_ID, INVALID_ID);
437 rows[1]=row_iter_map[row_it];
438 lpx_del_rows(lp, 1, rows);
439 row_iter_map[row_it]=0; //glpk specifikus
441 for (row_iter_map.first(it, VALID_ID);
442 row_iter_map.valid(it); row_iter_map.next(it)) {
443 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
447 void setColBounds(const ColIt& col_it, int bound_type,
448 double lo, double up) {
449 lpx_set_col_bnds(lp, col_iter_map[col_it], bound_type, lo, up);
452 double getObjCoef(const ColIt& col_it) {
453 return lpx_get_obj_coef(lp, col_iter_map[col_it]);
456 void setRowBounds(const RowIt& row_it, int bound_type,
457 double lo, double up) {
458 lpx_set_row_bnds(lp, row_iter_map[row_it], bound_type, lo, up);
461 void setObjCoef(const ColIt& col_it, double obj_coef) {
462 lpx_set_obj_coef(lp, col_iter_map[col_it], obj_coef);
465 void solveSimplex() { lpx_simplex(lp); }
467 void solvePrimalSimplex() { lpx_simplex(lp); }
469 void solveDualSimplex() { lpx_simplex(lp); }
471 double getPrimal(const ColIt& col_it) {
472 return lpx_get_col_prim(lp, col_iter_map[col_it]);
475 double getObjVal() { return lpx_get_obj_val(lp); }
477 int rowNum() const { return lpx_get_num_rows(lp); }
479 int colNum() const { return lpx_get_num_cols(lp); }
481 int warmUp() { return lpx_warm_up(lp); }
483 void printWarmUpStatus(int i) {
485 case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
486 case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;
487 case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
488 case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
492 int getPrimalStatus() { return lpx_get_prim_stat(lp); }
494 void printPrimalStatus(int i) {
496 case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
497 case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;
498 case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
499 case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
503 int getDualStatus() { return lpx_get_dual_stat(lp); }
505 void printDualStatus(int i) {
507 case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
508 case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;
509 case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
510 case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
513 /// Returns the status of the slack variable assigned to row \c row_it.
514 int getRowStat(const RowIt& row_it) {
515 return lpx_get_row_stat(lp, row_iter_map[row_it]);
518 void printRowStatus(int i) {
520 case LPX_BS: cout << "LPX_BS" << endl; break;
521 case LPX_NL: cout << "LPX_NL" << endl; break;
522 case LPX_NU: cout << "LPX_NU" << endl; break;
523 case LPX_NF: cout << "LPX_NF" << endl; break;
524 case LPX_NS: cout << "LPX_NS" << endl; break;
527 /// Returns the status of the variable assigned to column \c col_it.
528 int getColStat(const ColIt& col_it) {
529 return lpx_get_col_stat(lp, col_iter_map[col_it]);
532 void printColStatus(int i) {
534 case LPX_BS: cout << "LPX_BS" << endl; break;
535 case LPX_NL: cout << "LPX_NL" << endl; break;
536 case LPX_NU: cout << "LPX_NU" << endl; break;
537 case LPX_NF: cout << "LPX_NF" << endl; break;
538 case LPX_NS: cout << "LPX_NS" << endl; break;
547 #endif //LEMON_LP_SOLVER_WRAPPER_H