196 ///(\ref Col "Col"s) and also has a constant component. |
196 ///(\ref Col "Col"s) and also has a constant component. |
197 /// |
197 /// |
198 ///There are several ways to access and modify the contents of this |
198 ///There are several ways to access and modify the contents of this |
199 ///container. |
199 ///container. |
200 ///- Its it fully compatible with \c std::map<Col,double>, so for expamle |
200 ///- Its it fully compatible with \c std::map<Col,double>, so for expamle |
201 ///if \c e is an Expr and \c v and \c w are of type \ref Col then you can |
201 ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can |
202 ///read and modify the coefficients like |
202 ///read and modify the coefficients like |
203 ///these. |
203 ///these. |
204 ///\code |
204 ///\code |
205 ///e[v]=5; |
205 ///e[v]=5; |
206 ///e[v]+=12; |
206 ///e[v]+=12; |
316 } |
316 } |
317 }; |
317 }; |
318 |
318 |
319 ///Linear constraint |
319 ///Linear constraint |
320 |
320 |
321 ///\todo document please |
321 ///This data stucture represents a linear constraint in the LP. |
322 /// |
322 ///Basically it is a linear expression with a lower or an upper bound |
|
323 ///(or both). These parts of the constraint can be obtained by the member |
|
324 ///functions \ref expr(), \ref lowerBound() and \ref upperBound(), |
|
325 ///respectively. |
|
326 ///There are two ways to construct a constraint. |
|
327 ///- You can set the linear expression and the bounds directly |
|
328 /// by the functions above. |
|
329 ///- The operators <tt>\<=</tt>, <tt>==</tt> and <tt>\>=</tt> |
|
330 /// are defined between expressions, or even between constraints whenever |
|
331 /// it makes sense. Therefore if \c e and \c f are linear expressions and |
|
332 /// \c s and \c t are numbers, then the followings are valid expressions |
|
333 /// and thus they can be used directly e.g. in \ref addRow() whenever |
|
334 /// it makes sense. |
|
335 /// \code |
|
336 /// e<=s |
|
337 /// e<=f |
|
338 /// s<=e<=t |
|
339 /// e>=t |
|
340 /// \endcode |
|
341 ///\warning The validity of a constraint is checked only at run time, so |
|
342 ///e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will compile, but will throw a |
|
343 ///\ref LogicError exception. |
323 class Constr |
344 class Constr |
324 { |
345 { |
325 public: |
346 public: |
326 typedef LpSolverBase::Expr Expr; |
347 typedef LpSolverBase::Expr Expr; |
327 typedef Expr::Key Key; |
348 typedef Expr::Key Key; |
328 typedef Expr::Value Value; |
349 typedef Expr::Value Value; |
329 |
350 |
330 static const Value INF; |
351 // static const Value INF; |
331 static const Value NaN; |
352 // static const Value NaN; |
332 // static const Value INF=0; |
353 |
333 // static const Value NaN=1; |
|
334 |
|
335 protected: |
354 protected: |
336 Expr _expr; |
355 Expr _expr; |
337 Value _lb,_ub; |
356 Value _lb,_ub; |
338 public: |
357 public: |
339 ///\e |
358 ///\e |
354 void clear() |
373 void clear() |
355 { |
374 { |
356 _expr.clear(); |
375 _expr.clear(); |
357 _lb=_ub=NaN; |
376 _lb=_ub=NaN; |
358 } |
377 } |
359 ///\e |
378 |
|
379 ///Reference to the linear expression |
360 Expr &expr() { return _expr; } |
380 Expr &expr() { return _expr; } |
361 ///\e |
381 ///Cont reference to the linear expression |
362 const Expr &expr() const { return _expr; } |
382 const Expr &expr() const { return _expr; } |
363 ///\e |
383 ///Reference to the lower bound. |
|
384 |
|
385 ///\return |
|
386 ///- -\ref INF: the constraint is lower unbounded. |
|
387 ///- -\ref NaN: lower bound has not been set. |
|
388 ///- finite number: the lower bound |
364 Value &lowerBound() { return _lb; } |
389 Value &lowerBound() { return _lb; } |
365 ///\e |
390 ///The const version of \ref lowerBound() |
366 const Value &lowerBound() const { return _lb; } |
391 const Value &lowerBound() const { return _lb; } |
367 ///\e |
392 ///Reference to the upper bound. |
|
393 |
|
394 ///\return |
|
395 ///- -\ref INF: the constraint is upper unbounded. |
|
396 ///- -\ref NaN: upper bound has not been set. |
|
397 ///- finite number: the upper bound |
368 Value &upperBound() { return _ub; } |
398 Value &upperBound() { return _ub; } |
369 ///\e |
399 ///The const version of \ref upperBound() |
370 const Value &upperBound() const { return _ub; } |
400 const Value &upperBound() const { return _ub; } |
371 ///\e |
401 ///Is the constraint lower bounded? |
372 bool lowerBounded() const { |
402 bool lowerBounded() const { |
373 using namespace std; |
403 using namespace std; |
374 return isfinite(_lb); |
404 return isfinite(_lb); |
375 } |
405 } |
376 ///\e |
406 ///Is the constraint upper bounded? |
377 bool upperBounded() const { |
407 bool upperBounded() const { |
378 using namespace std; |
408 using namespace std; |
379 return isfinite(_ub); |
409 return isfinite(_ub); |
380 } |
410 } |
381 }; |
411 }; |
384 protected: |
414 protected: |
385 _FixId rows; |
415 _FixId rows; |
386 _FixId cols; |
416 _FixId cols; |
387 |
417 |
388 //Abstract virtual functions |
418 //Abstract virtual functions |
|
419 virtual LpSolverBase &_newLp() = 0; |
|
420 virtual LpSolverBase &_copyLp() = 0; |
|
421 |
389 virtual int _addCol() = 0; |
422 virtual int _addCol() = 0; |
390 virtual int _addRow() = 0; |
423 virtual int _addRow() = 0; |
391 virtual void _setRowCoeffs(int i, |
424 virtual void _setRowCoeffs(int i, |
392 int length, |
425 int length, |
393 int const * indices, |
426 int const * indices, |
424 LpSolverBase() : obj_const_comp(0) {} |
457 LpSolverBase() : obj_const_comp(0) {} |
425 |
458 |
426 ///\e |
459 ///\e |
427 virtual ~LpSolverBase() {} |
460 virtual ~LpSolverBase() {} |
428 |
461 |
|
462 ///Creates a new LP problem |
|
463 LpSolverBase &newLp() {return _newLp();} |
|
464 ///Make a copy of the LP problem |
|
465 LpSolverBase ©Lp() {return _copyLp();} |
|
466 |
429 ///\name Build up and modify of the LP |
467 ///\name Build up and modify of the LP |
430 |
468 |
431 ///@{ |
469 ///@{ |
432 |
470 |
433 ///Add a new empty column (i.e a new variable) to the LP |
471 ///Add a new empty column (i.e a new variable) to the LP |
449 ///\endcode |
487 ///\endcode |
450 ///- a standard STL compatible iterable container with |
488 ///- a standard STL compatible iterable container with |
451 ///\ref Col as its \c mapped_type |
489 ///\ref Col as its \c mapped_type |
452 ///like |
490 ///like |
453 ///\code |
491 ///\code |
454 ///std::map<AnyStatus,LpSolverBase::Col> |
492 ///std::map<AnyType,LpSolverBase::Col> |
455 ///\endcode |
493 ///\endcode |
456 ///- an iterable lemon \ref concept::WriteMap "write map" like |
494 ///- an iterable lemon \ref concept::WriteMap "write map" like |
457 ///\code |
495 ///\code |
458 ///ListGraph::NodeMap<LpSolverBase::Col> |
496 ///ListGraph::NodeMap<LpSolverBase::Col> |
459 ///ListGraph::EdgeMap<LpSolverBase::Col> |
497 ///ListGraph::EdgeMap<LpSolverBase::Col> |
460 ///\endcode |
498 ///\endcode |
461 ///\return The number of the created column. |
499 ///\return The number of the created column. |
462 ///\bug Iterable nodemap hasn't been implemented yet. |
|
463 #ifdef DOXYGEN |
500 #ifdef DOXYGEN |
464 template<class T> |
501 template<class T> |
465 int addColSet(T &t) { return 0;} |
502 int addColSet(T &t) { return 0;} |
466 #else |
503 #else |
467 template<class T> |
504 template<class T> |
666 ///\e |
703 ///\e |
667 |
704 |
668 ///\return |
705 ///\return |
669 ///- \ref INF or -\ref INF means either infeasibility or unboundedness |
706 ///- \ref INF or -\ref INF means either infeasibility or unboundedness |
670 /// of the primal problem, depending on whether we minimize or maximize. |
707 /// of the primal problem, depending on whether we minimize or maximize. |
671 ///- \ref NAN if no primal solution is found. |
708 ///- \ref NaN if no primal solution is found. |
672 ///- The (finite) objective value if an optimal solution is found. |
709 ///- The (finite) objective value if an optimal solution is found. |
673 Value primalValue() { return _getPrimalValue()+obj_const_comp;} |
710 Value primalValue() { return _getPrimalValue()+obj_const_comp;} |
674 ///@} |
711 ///@} |
675 |
712 |
676 }; |
713 }; |
681 /// |
718 /// |
682 inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a, |
719 inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a, |
683 const LpSolverBase::Expr &b) |
720 const LpSolverBase::Expr &b) |
684 { |
721 { |
685 LpSolverBase::Expr tmp(a); |
722 LpSolverBase::Expr tmp(a); |
686 tmp+=b; ///\todo Don't STL have some special 'merge' algorithm? |
723 tmp+=b; ///\todo Doesn't STL have some special 'merge' algorithm? |
687 return tmp; |
724 return tmp; |
688 } |
725 } |
689 ///\e |
726 ///\e |
690 |
727 |
691 ///\relates LpSolverBase::Expr |
728 ///\relates LpSolverBase::Expr |
692 /// |
729 /// |
693 inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a, |
730 inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a, |
694 const LpSolverBase::Expr &b) |
731 const LpSolverBase::Expr &b) |
695 { |
732 { |
696 LpSolverBase::Expr tmp(a); |
733 LpSolverBase::Expr tmp(a); |
697 tmp-=b; ///\todo Don't STL have some special 'merge' algorithm? |
734 tmp-=b; ///\todo Doesn't STL have some special 'merge' algorithm? |
698 return tmp; |
735 return tmp; |
699 } |
736 } |
700 ///\e |
737 ///\e |
701 |
738 |
702 ///\relates LpSolverBase::Expr |
739 ///\relates LpSolverBase::Expr |
703 /// |
740 /// |
704 inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a, |
741 inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a, |
705 const LpSolverBase::Value &b) |
742 const LpSolverBase::Value &b) |
706 { |
743 { |
707 LpSolverBase::Expr tmp(a); |
744 LpSolverBase::Expr tmp(a); |
708 tmp*=b; ///\todo Don't STL have some special 'merge' algorithm? |
745 tmp*=b; ///\todo Doesn't STL have some special 'merge' algorithm? |
709 return tmp; |
746 return tmp; |
710 } |
747 } |
711 |
748 |
712 ///\e |
749 ///\e |
713 |
750 |
715 /// |
752 /// |
716 inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a, |
753 inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a, |
717 const LpSolverBase::Expr &b) |
754 const LpSolverBase::Expr &b) |
718 { |
755 { |
719 LpSolverBase::Expr tmp(b); |
756 LpSolverBase::Expr tmp(b); |
720 tmp*=a; ///\todo Don't STL have some special 'merge' algorithm? |
757 tmp*=a; ///\todo Doesn't STL have some special 'merge' algorithm? |
721 return tmp; |
758 return tmp; |
722 } |
759 } |
723 ///\e |
760 ///\e |
724 |
761 |
725 ///\relates LpSolverBase::Expr |
762 ///\relates LpSolverBase::Expr |
726 /// |
763 /// |
727 inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a, |
764 inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a, |
728 const LpSolverBase::Value &b) |
765 const LpSolverBase::Value &b) |
729 { |
766 { |
730 LpSolverBase::Expr tmp(a); |
767 LpSolverBase::Expr tmp(a); |
731 tmp/=b; ///\todo Don't STL have some special 'merge' algorithm? |
768 tmp/=b; ///\todo Doesn't STL have some special 'merge' algorithm? |
732 return tmp; |
769 return tmp; |
733 } |
770 } |
734 |
771 |
735 ///\e |
772 ///\e |
736 |
773 |