2 #ifndef LEMON_LP_SOLVER_BASE_H
3 #define LEMON_LP_SOLVER_BASE_H
23 #include <lemon/invalid.h>
24 #include <expression.h>
26 //#include <lemon/max_flow.h>
27 //#include <augmenting_flow.h>
28 //#include <iter_map.h>
39 /// \brief A partitioned vector with iterable classes.
41 /// This class implements a container in which the data is stored in an
42 /// stl vector, the range is partitioned into sets and each set is
43 /// doubly linked in a list.
44 /// That is, each class is iterable by lemon iterators, and any member of
45 /// the vector can bo moved to an other class.
47 class IterablePartition {
51 int prev; //invalid az -1
54 std::vector<Node> nodes;
59 std::vector<Tip> tips;
61 /// The classes are indexed by integers from \c 0 to \c classNum()-1.
62 int classNum() const { return tips.size(); }
63 /// This lemon style iterator iterates through a class.
65 /// Constructor. The number of classes is to be given which is fixed
66 /// over the life of the container.
67 /// The partition classes are indexed from 0 to class_num-1.
68 IterablePartition(int class_num) {
69 for (int i=0; i<class_num; ++i) {
76 void befuz(Class it, int class_id) {
77 if (tips[class_id].first==-1) {
78 if (tips[class_id].last==-1) {
79 nodes[it.i].prev=nodes[it.i].next=-1;
80 tips[class_id].first=tips[class_id].last=it.i;
83 nodes[it.i].prev=tips[class_id].last;
85 nodes[tips[class_id].last].next=it.i;
86 tips[class_id].last=it.i;
89 void kifuz(Class it, int class_id) {
90 if (tips[class_id].first==it.i) {
91 if (tips[class_id].last==it.i) {
92 tips[class_id].first=tips[class_id].last=-1;
94 tips[class_id].first=nodes[it.i].next;
95 nodes[nodes[it.i].next].prev=-1;
98 if (tips[class_id].last==it.i) {
99 tips[class_id].last=nodes[it.i].prev;
100 nodes[nodes[it.i].prev].next=-1;
102 nodes[nodes[it.i].next].prev=nodes[it.i].prev;
103 nodes[nodes[it.i].prev].next=nodes[it.i].next;
108 /// A new element with data \c t is pushed into the vector and into class
110 Class push_back(const T& t, int class_id) {
114 int i=nodes.size()-1;
118 /// A member is moved to an other class.
119 void set(Class it, int old_class_id, int new_class_id) {
120 kifuz(it.i, old_class_id);
121 befuz(it.i, new_class_id);
123 /// Returns the data pointed by \c it.
124 T& operator[](Class it) { return nodes[it.i].data; }
125 /// Returns the data pointed by \c it.
126 const T& operator[](Class it) const { return nodes[it.i].data; }
129 friend class IterablePartition;
133 /// Default constructor.
135 /// This constructor constructs an iterator which points
136 /// to the member of th container indexed by the integer _i.
137 Class(const int& _i) : i(_i) { }
138 /// Invalid constructor.
139 Class(const Invalid&) : i(-1) { }
140 friend bool operator<(const Class& x, const Class& y);
141 friend std::ostream& operator<<(std::ostream& os,
143 bool operator==(const Class& node) const {return i == node.i;}
144 bool operator!=(const Class& node) const {return i != node.i;}
146 friend bool operator<(const Class& x, const Class& y) {
149 friend std::ostream& operator<<(std::ostream& os,
154 /// First member of class \c class_id.
155 Class& first(Class& it, int class_id) const {
156 it.i=tips[class_id].first;
160 Class& next(Class& it) const {
161 it.i=nodes[it.i].next;
164 /// True iff the iterator is valid.
165 bool valid(const Class& it) const { return it.i!=-1; }
167 class ClassIt : public Class {
168 const IterablePartition* iterable_partition;
171 ClassIt(Invalid i) : Class(i) { }
172 ClassIt(const IterablePartition& _iterable_partition,
173 const int& i) : iterable_partition(&_iterable_partition) {
174 _iterable_partition.first(*this, i);
176 ClassIt(const IterablePartition& _iterable_partition,
177 const Class& _class) :
178 Class(_class), iterable_partition(&_iterable_partition) { }
179 ClassIt& operator++() {
180 iterable_partition->next(*this);
189 \todo kellenene uj iterable structure bele, mert ez nem az igazi
190 \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
191 \todo LEKERDEZESEK!!!
192 \todo DOKSI!!!! Doxygen group!!!
193 The aim of this class is to give a general surface to different
194 solvers, i.e. it makes possible to write algorithms using LP's,
195 in which the solver can be changed to an other one easily.
198 template <typename _Value>
201 /*! @name Uncategorized functions and types (public members)
209 typedef IterablePartition<int> Rows;
211 typedef IterablePartition<int> Cols;
213 typedef _Value Value;
215 typedef Rows::Class Row;
217 typedef Cols::Class Col;
220 IterablePartition<int> row_iter_map;
222 IterablePartition<int> col_iter_map;
224 std::vector<Row> int_row_map;
226 std::vector<Col> int_col_map;
228 const int VALID_CLASS;
230 const int INVALID_CLASS;
232 static const Value INF;
235 LpSolverBase() : row_iter_map(2),
237 VALID_CLASS(0), INVALID_CLASS(1) { }
239 virtual ~LpSolverBase() { }
242 /*! @name Medium level interface (public members)
243 These functions appear in the low level and also in the high level
244 interfaces thus these each of these functions have to be implemented
245 only once in the different interfaces.
246 This means that these functions have to be reimplemented for all of the
247 different lp solvers. These are basic functions, and have the same
248 parameter lists in the low and high level interfaces.
253 //UNCATEGORIZED FUNCTIONS
256 virtual void setMinimize() = 0;
258 virtual void setMaximize() = 0;
263 virtual void solveSimplex() = 0;
265 virtual void solvePrimalSimplex() = 0;
267 virtual void solveDualSimplex() = 0;
269 //SOLUTION RETRIEVING
272 virtual Value getObjVal() = 0;
277 virtual int rowNum() const = 0;
279 virtual int colNum() const = 0;
281 virtual int warmUp() = 0;
283 virtual void printWarmUpStatus(int i) = 0;
285 virtual int getPrimalStatus() = 0;
287 virtual void printPrimalStatus(int i) = 0;
289 virtual int getDualStatus() = 0;
291 virtual void printDualStatus(int i) = 0;
292 /// Returns the status of the slack variable assigned to row \c row.
293 virtual int getRowStat(const Row& row) = 0;
295 virtual void printRowStatus(int i) = 0;
296 /// Returns the status of the variable assigned to column \c col.
297 virtual int getColStat(const Col& col) = 0;
299 virtual void printColStatus(int i) = 0;
303 /*! @name Low level interface (protected members)
304 Problem manipulating functions in the low level interface
309 //MATRIX MANIPULATING FUNCTIONS
312 virtual int _addCol() = 0;
314 virtual int _addRow() = 0;
316 virtual void _eraseCol(int i) = 0;
318 virtual void _eraseRow(int i) = 0;
320 virtual void _setRowCoeffs(int i,
321 const std::vector<std::pair<int, Value> >& coeffs) = 0;
323 /// This routine modifies \c coeffs only by the \c push_back method.
324 virtual void _getRowCoeffs(int i,
325 std::vector<std::pair<int, Value> >& coeffs) = 0;
327 virtual void _setColCoeffs(int i,
328 const std::vector<std::pair<int, Value> >& coeffs) = 0;
330 /// This routine modifies \c coeffs only by the \c push_back method.
331 virtual void _getColCoeffs(int i,
332 std::vector<std::pair<int, Value> >& coeffs) = 0;
334 virtual void _setCoeff(int col, int row, Value value) = 0;
336 virtual Value _getCoeff(int col, int row) = 0;
339 // enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
342 /// The lower bound of a variable (column) have to be given by an
343 /// extended number of type Value, i.e. a finite number of type
345 virtual void _setColLowerBound(int i, Value value) = 0;
347 /// The lower bound of a variable (column) is an
348 /// extended number of type Value, i.e. a finite number of type
350 virtual Value _getColLowerBound(int i) = 0;
352 /// The upper bound of a variable (column) have to be given by an
353 /// extended number of type Value, i.e. a finite number of type
355 virtual void _setColUpperBound(int i, Value value) = 0;
357 /// The upper bound of a variable (column) is an
358 /// extended number of type Value, i.e. a finite number of type
360 virtual Value _getColUpperBound(int i) = 0;
362 /// The lower bound of a linear expression (row) have to be given by an
363 /// extended number of type Value, i.e. a finite number of type
365 virtual void _setRowLowerBound(int i, Value value) = 0;
367 /// The lower bound of a linear expression (row) is an
368 /// extended number of type Value, i.e. a finite number of type
370 virtual Value _getRowLowerBound(int i) = 0;
372 /// The upper bound of a linear expression (row) have to be given by an
373 /// extended number of type Value, i.e. a finite number of type
375 virtual void _setRowUpperBound(int i, Value value) = 0;
377 /// The upper bound of a linear expression (row) is an
378 /// extended number of type Value, i.e. a finite number of type
380 virtual Value _getRowUpperBound(int i) = 0;
382 virtual void _setObjCoeff(int i, Value obj_coef) = 0;
384 virtual Value _getObjCoeff(int i) = 0;
386 //SOLUTION RETRIEVING
389 virtual Value _getPrimal(int i) = 0;
392 /*! @name High level interface (public members)
393 Problem manipulating functions in the high level interface
398 //MATRIX MANIPULATING FUNCTIONS
404 col_iter_map.first(col, INVALID_CLASS);
405 if (col_iter_map.valid(col)) { //van hasznalhato hely
406 col_iter_map.set(col, INVALID_CLASS, VALID_CLASS);
408 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
409 col=col_iter_map.push_back(i, VALID_CLASS);
411 int_col_map.push_back(col);
418 row_iter_map.first(row, INVALID_CLASS);
419 if (row_iter_map.valid(row)) { //van hasznalhato hely
420 row_iter_map.set(row, INVALID_CLASS, VALID_CLASS);
422 } else { //a cucc vegere kell inzertalni mert nincs szabad hely
423 row=row_iter_map.push_back(i, VALID_CLASS);
425 int_row_map.push_back(row);
429 void eraseCol(const Col& col) {
430 col_iter_map.set(col, VALID_CLASS, INVALID_CLASS);
432 cols[1]=col_iter_map[col];
434 col_iter_map[col]=0; //glpk specifikus, de kell ez??
436 for (col_iter_map.first(it, VALID_CLASS);
437 col_iter_map.valid(it); col_iter_map.next(it)) {
438 if (col_iter_map[it]>cols[1]) --col_iter_map[it];
440 int_col_map.erase(int_col_map.begin()+cols[1]);
443 void eraseRow(const Row& row) {
444 row_iter_map.set(row, VALID_CLASS, INVALID_CLASS);
446 rows[1]=row_iter_map[row];
448 row_iter_map[row]=0; //glpk specifikus, de kell ez??
450 for (row_iter_map.first(it, VALID_CLASS);
451 row_iter_map.valid(it); row_iter_map.next(it)) {
452 if (row_iter_map[it]>rows[1]) --row_iter_map[it];
454 int_row_map.erase(int_row_map.begin()+rows[1]);
457 void setCoeff(Col col, Row row, Value value) {
458 _setCoeff(col_iter_map[col], row_iter_map[row], value);
461 Value getCoeff(Col col, Row row) {
462 return _getCoeff(col_iter_map[col], row_iter_map[row], value);
465 void setColLowerBound(Col col, Value lo) {
466 _setColLowerBound(col_iter_map[col], lo);
469 Value getColLowerBound(Col col) {
470 return _getColLowerBound(col_iter_map[col]);
473 void setColUpperBound(Col col, Value up) {
474 _setColUpperBound(col_iter_map[col], up);
477 Value getColUpperBound(Col col) {
478 return _getColUpperBound(col_iter_map[col]);
481 void setRowLowerBound(Row row, Value lo) {
482 _setRowLowerBound(row_iter_map[row], lo);
485 Value getRowLowerBound(Row row) {
486 return _getRowLowerBound(row_iter_map[row]);
489 void setRowUpperBound(Row row, Value up) {
490 _setRowUpperBound(row_iter_map[row], up);
493 Value getRowUpperBound(Row row) {
494 return _getRowUpperBound(row_iter_map[row]);
497 void setObjCoeff(const Col& col, Value obj_coef) {
498 _setObjCoeff(col_iter_map[col], obj_coef);
501 Value getObjCoeff(const Col& col) {
502 return _getObjCoeff(col_iter_map[col]);
505 //SOLUTION RETRIEVING FUNCTIONS
508 Value getPrimal(const Col& col) {
509 return _getPrimal(col_iter_map[col]);
514 /*! @name User friend interface
515 Problem manipulating functions in the user friend interface
522 typedef Expr<Col, Value> Expression;
524 typedef Expr<Row, Value> DualExpression;
526 typedef Constr<Col, Value> Constraint;
528 //MATRIX MANIPULATING FUNCTIONS
531 void setRowCoeffs(Row row, const Expression& expr) {
532 std::vector<std::pair<int, Value> > row_coeffs;
533 for(typename Expression::Data::const_iterator i=expr.data.begin();
534 i!=expr.data.end(); ++i) {
535 row_coeffs.push_back(std::make_pair
536 (col_iter_map[(*i).first], (*i).second));
538 _setRowCoeffs(row_iter_map[row], row_coeffs);
541 void setRow(Row row, const Constraint& constr) {
542 setRowCoeffs(row, constr.expr);
543 setRowLowerBound(row, constr.lo);
544 setRowUpperBound(row, constr.up);
547 Row addRow(const Constraint& constr) {
549 setRowCoeffs(row, constr.expr);
550 setRowLowerBound(row, constr.lo);
551 setRowUpperBound(row, constr.up);
555 /// This routine modifies \c expr by only adding to it.
556 void getRowCoeffs(Row row, Expression& expr) {
557 std::vector<std::pair<int, Value> > row_coeffs;
558 _getRowCoeffs(row_iter_map[row], row_coeffs);
559 for(typename std::vector<std::pair<int, Value> >::const_iterator
560 i=row_coeffs.begin(); i!=row_coeffs.end(); ++i) {
561 expr+= (*i).second*int_col_map[(*i).first];
565 void setColCoeffs(Col col, const DualExpression& expr) {
566 std::vector<std::pair<int, Value> > col_coeffs;
567 for(typename DualExpression::Data::const_iterator i=expr.data.begin();
568 i!=expr.data.end(); ++i) {
569 col_coeffs.push_back(std::make_pair
570 (row_iter_map[(*i).first], (*i).second));
572 _setColCoeffs(col_iter_map[col], col_coeffs);
575 /// This routine modifies \c expr by only adding to it.
576 void getColCoeffs(Col col, DualExpression& expr) {
577 std::vector<std::pair<int, Value> > col_coeffs;
578 _getColCoeffs(col_iter_map[col], col_coeffs);
579 for(typename std::vector<std::pair<int, Value> >::const_iterator
580 i=col_coeffs.begin(); i!=col_coeffs.end(); ++i) {
581 expr+= (*i).second*int_row_map[(*i).first];
585 void setObjCoeffs(const Expression& expr) {
586 // writing zero everywhere
587 for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
588 setObjCoeff(it, 0.0);
589 // writing the data needed
590 for(typename Expression::Data::const_iterator i=expr.data.begin();
591 i!=expr.data.end(); ++i) {
592 setObjCoeff((*i).first, (*i).second);
596 /// This routine modifies \c expr by only adding to it.
597 void getObjCoeffs(Expression& expr) {
598 for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
599 expr+=getObjCoeff(it)*it;
604 /*! @name MIP functions and types (public members)
609 virtual void solveBandB() = 0;
611 virtual void setLP() = 0;
613 virtual void setMIP() = 0;
616 virtual void _setColCont(int i) = 0;
618 virtual void _setColInt(int i) = 0;
620 virtual Value _getMIPPrimal(int i) = 0;
623 void setColCont(Col col) {
624 _setColCont(col_iter_map[col]);
627 void setColInt(Col col) {
628 _setColInt(col_iter_map[col]);
631 Value getMIPPrimal(Col col) {
632 return _getMIPPrimal(col_iter_map[col]);
639 #endif //LEMON_LP_SOLVER_BASE_H