COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_base.h @ 1875:98698b69a902

Last change on this file since 1875:98698b69a902 was 1875:98698b69a902, checked in by Alpar Juttner, 18 years ago

Happy new year to LEMON

File size: 34.7 KB
Line 
1/* -*- C++ -*-
2 * lemon/lp_base.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17#ifndef LEMON_LP_BASE_H
18#define LEMON_LP_BASE_H
19
20#include<vector>
21#include<map>
22#include<limits>
23#include<cmath>
24
25#include<lemon/utility.h>
26#include<lemon/error.h>
27#include<lemon/invalid.h>
28
29///\file
30///\brief The interface of the LP solver interface.
31///\ingroup gen_opt_group
32namespace lemon {
33 
34  ///Internal data structure to convert floating id's to fix one's
35   
36  ///\todo This might be implemented to be also usable in other places.
37  class _FixId
38  {
39  protected:
40    std::vector<int> index;
41    std::vector<int> cross;
42    int first_free;
43  public:
44    _FixId() : first_free(-1) {};
45    ///Convert a floating id to a fix one
46
47    ///\param n is a floating id
48    ///\return the corresponding fix id
49    int fixId(int n) const {return cross[n];}
50    ///Convert a fix id to a floating one
51
52    ///\param n is a fix id
53    ///\return the corresponding floating id
54    int floatingId(int n) const { return index[n];}
55    ///Add a new floating id.
56
57    ///\param n is a floating id
58    ///\return the fix id of the new value
59    ///\todo Multiple additions should also be handled.
60    int insert(int n)
61    {
62      if(n>=int(cross.size())) {
63        cross.resize(n+1);
64        if(first_free==-1) {
65          cross[n]=index.size();
66          index.push_back(n);
67        }
68        else {
69          cross[n]=first_free;
70          int next=index[first_free];
71          index[first_free]=n;
72          first_free=next;
73        }
74        return cross[n];
75      }
76      ///\todo Create an own exception type.
77      else throw LogicError(); //floatingId-s must form a continuous range;
78    }
79    ///Remove a fix id.
80
81    ///\param n is a fix id
82    ///
83    void erase(int n)
84    {
85      int fl=index[n];
86      index[n]=first_free;
87      first_free=n;
88      for(int i=fl+1;i<int(cross.size());++i) {
89        cross[i-1]=cross[i];
90        index[cross[i]]--;
91      }
92      cross.pop_back();
93    }
94    ///An upper bound on the largest fix id.
95
96    ///\todo Do we need this?
97    ///
98    std::size_t maxFixId() { return cross.size()-1; }
99 
100  };
101   
102  ///Common base class for LP solvers
103 
104  ///\todo Much more docs
105  ///\ingroup gen_opt_group
106  class LpSolverBase {
107
108  public:
109
110    ///Possible outcomes of an LP solving procedure
111    enum SolveExitStatus {
112      ///This means that the problem has been successfully solved: either
113      ///an optimal solution has been found or infeasibility/unboundedness
114      ///has been proved.
115      SOLVED = 0,
116      ///Any other case (including the case when some user specified limit has been exceeded)
117      UNSOLVED = 1
118    };
119     
120      ///\e
121    enum SolutionStatus {
122      ///Feasible solution has'n been found (but may exist).
123
124      ///\todo NOTFOUND might be a better name.
125      ///
126      UNDEFINED = 0,
127      ///The problem has no feasible solution
128      INFEASIBLE = 1,
129      ///Feasible solution found
130      FEASIBLE = 2,
131      ///Optimal solution exists and found
132      OPTIMAL = 3,
133      ///The cost function is unbounded
134
135      ///\todo Give a feasible solution and an infinite ray (and the
136      ///corresponding bases)
137      INFINITE = 4
138    };
139
140    ///\e The type of the investigated LP problem
141    enum ProblemTypes {
142      ///Primal-dual feasible
143      PRIMAL_DUAL_FEASIBLE = 0,
144      ///Primal feasible dual infeasible
145      PRIMAL_FEASIBLE_DUAL_INFEASIBLE = 1,
146      ///Primal infeasible dual feasible
147      PRIMAL_INFEASIBLE_DUAL_FEASIBLE = 2,
148      ///Primal-dual infeasible
149      PRIMAL_DUAL_INFEASIBLE = 3,
150      ///Could not determine so far
151      UNKNOWN = 4
152    };
153
154    ///The floating point type used by the solver
155    typedef double Value;
156    ///The infinity constant
157    static const Value INF;
158    ///The not a number constant
159    static const Value NaN;
160   
161    ///Refer to a column of the LP.
162
163    ///This type is used to refer to a column of the LP.
164    ///
165    ///Its value remains valid and correct even after the addition or erase of
166    ///other columns.
167    ///
168    ///\todo Document what can one do with a Col (INVALID, comparing,
169    ///it is similar to Node/Edge)
170    class Col {
171    protected:
172      int id;
173      friend class LpSolverBase;
174    public:
175      typedef Value ExprValue;
176      typedef True LpSolverCol;
177      Col() {}
178      Col(const Invalid&) : id(-1) {}
179      bool operator<(Col c) const  {return id<c.id;}
180      bool operator==(Col c) const  {return id==c.id;}
181      bool operator!=(Col c) const  {return id==c.id;}
182    };
183
184    ///Refer to a row of the LP.
185
186    ///This type is used to refer to a row of the LP.
187    ///
188    ///Its value remains valid and correct even after the addition or erase of
189    ///other rows.
190    ///
191    ///\todo Document what can one do with a Row (INVALID, comparing,
192    ///it is similar to Node/Edge)
193    class Row {
194    protected:
195      int id;
196      friend class LpSolverBase;
197    public:
198      typedef Value ExprValue;
199      typedef True LpSolverRow;
200      Row() {}
201      Row(const Invalid&) : id(-1) {}
202
203      bool operator<(Row c) const  {return id<c.id;}
204      bool operator==(Row c) const  {return id==c.id;}
205      bool operator!=(Row c) const  {return id==c.id;}
206   };
207   
208    ///Linear expression of variables and a constant component
209   
210    ///This data structure strores a linear expression of the variables
211    ///(\ref Col "Col"s) and also has a constant component.
212    ///
213    ///There are several ways to access and modify the contents of this
214    ///container.
215    ///- Its it fully compatible with \c std::map<Col,double>, so for expamle
216    ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can
217    ///read and modify the coefficients like
218    ///these.
219    ///\code
220    ///e[v]=5;
221    ///e[v]+=12;
222    ///e.erase(v);
223    ///\endcode
224    ///or you can also iterate through its elements.
225    ///\code
226    ///double s=0;
227    ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i)
228    ///  s+=i->second;
229    ///\endcode
230    ///(This code computes the sum of all coefficients).
231    ///- Numbers (<tt>double</tt>'s)
232    ///and variables (\ref Col "Col"s) directly convert to an
233    ///\ref Expr and the usual linear operations are defined so 
234    ///\code
235    ///v+w
236    ///2*v-3.12*(v-w/2)+2
237    ///v*2.1+(3*v+(v*12+w+6)*3)/2
238    ///\endcode
239    ///are valid \ref Expr "Expr"essions.
240    ///The usual assignment operations are also defined.
241    ///\code
242    ///e=v+w;
243    ///e+=2*v-3.12*(v-w/2)+2;
244    ///e*=3.4;
245    ///e/=5;
246    ///\endcode
247    ///- The constant member can be set and read by \ref constComp()
248    ///\code
249    ///e.constComp()=12;
250    ///double c=e.constComp();
251    ///\endcode
252    ///
253    ///\note \ref clear() not only sets all coefficients to 0 but also
254    ///clears the constant components.
255    ///
256    ///\sa Constr
257    ///
258    class Expr : public std::map<Col,Value>
259    {
260    public:
261      typedef LpSolverBase::Col Key;
262      typedef LpSolverBase::Value Value;
263     
264    protected:
265      typedef std::map<Col,Value> Base;
266     
267      Value const_comp;
268  public:
269      typedef True IsLinExpression;
270      ///\e
271      Expr() : Base(), const_comp(0) { }
272      ///\e
273      Expr(const Key &v) : const_comp(0) {
274        Base::insert(std::make_pair(v, 1));
275      }
276      ///\e
277      Expr(const Value &v) : const_comp(v) {}
278      ///\e
279      void set(const Key &v,const Value &c) {
280        Base::insert(std::make_pair(v, c));
281      }
282      ///\e
283      Value &constComp() { return const_comp; }
284      ///\e
285      const Value &constComp() const { return const_comp; }
286     
287      ///Removes the components with zero coefficient.
288      void simplify() {
289        for (Base::iterator i=Base::begin(); i!=Base::end();) {
290          Base::iterator j=i;
291          ++j;
292          if ((*i).second==0) Base::erase(i);
293          j=i;
294        }
295      }
296
297      ///Removes the coefficients closer to zero than \c tolerance.
298      void simplify(double &tolerance) {
299        for (Base::iterator i=Base::begin(); i!=Base::end();) {
300          Base::iterator j=i;
301          ++j;
302          if (std::fabs((*i).second)<tolerance) Base::erase(i);
303          j=i;
304        }
305      }
306
307      ///Sets all coefficients and the constant component to 0.
308      void clear() {
309        Base::clear();
310        const_comp=0;
311      }
312
313      ///\e
314      Expr &operator+=(const Expr &e) {
315        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
316          (*this)[j->first]+=j->second;
317        const_comp+=e.const_comp;
318        return *this;
319      }
320      ///\e
321      Expr &operator-=(const Expr &e) {
322        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
323          (*this)[j->first]-=j->second;
324        const_comp-=e.const_comp;
325        return *this;
326      }
327      ///\e
328      Expr &operator*=(const Value &c) {
329        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
330          j->second*=c;
331        const_comp*=c;
332        return *this;
333      }
334      ///\e
335      Expr &operator/=(const Value &c) {
336        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
337          j->second/=c;
338        const_comp/=c;
339        return *this;
340      }
341    };
342   
343    ///Linear constraint
344
345    ///This data stucture represents a linear constraint in the LP.
346    ///Basically it is a linear expression with a lower or an upper bound
347    ///(or both). These parts of the constraint can be obtained by the member
348    ///functions \ref expr(), \ref lowerBound() and \ref upperBound(),
349    ///respectively.
350    ///There are two ways to construct a constraint.
351    ///- You can set the linear expression and the bounds directly
352    ///  by the functions above.
353    ///- The operators <tt>\<=</tt>, <tt>==</tt> and  <tt>\>=</tt>
354    ///  are defined between expressions, or even between constraints whenever
355    ///  it makes sense. Therefore if \c e and \c f are linear expressions and
356    ///  \c s and \c t are numbers, then the followings are valid expressions
357    ///  and thus they can be used directly e.g. in \ref addRow() whenever
358    ///  it makes sense.
359    ///  \code
360    ///  e<=s
361    ///  e<=f
362    ///  s<=e<=t
363    ///  e>=t
364    ///  \endcode
365    ///\warning The validity of a constraint is checked only at run time, so
366    ///e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will compile, but will throw a
367    ///\ref LogicError exception.
368    class Constr
369    {
370    public:
371      typedef LpSolverBase::Expr Expr;
372      typedef Expr::Key Key;
373      typedef Expr::Value Value;
374     
375//       static const Value INF;
376//       static const Value NaN;
377
378    protected:
379      Expr _expr;
380      Value _lb,_ub;
381    public:
382      ///\e
383      Constr() : _expr(), _lb(NaN), _ub(NaN) {}
384      ///\e
385      Constr(Value lb,const Expr &e,Value ub) :
386        _expr(e), _lb(lb), _ub(ub) {}
387      ///\e
388      Constr(const Expr &e,Value ub) :
389        _expr(e), _lb(NaN), _ub(ub) {}
390      ///\e
391      Constr(Value lb,const Expr &e) :
392        _expr(e), _lb(lb), _ub(NaN) {}
393      ///\e
394      Constr(const Expr &e) :
395        _expr(e), _lb(NaN), _ub(NaN) {}
396      ///\e
397      void clear()
398      {
399        _expr.clear();
400        _lb=_ub=NaN;
401      }
402
403      ///Reference to the linear expression
404      Expr &expr() { return _expr; }
405      ///Cont reference to the linear expression
406      const Expr &expr() const { return _expr; }
407      ///Reference to the lower bound.
408
409      ///\return
410      ///- \ref INF "INF": the constraint is lower unbounded.
411      ///- \ref NaN "NaN": lower bound has not been set.
412      ///- finite number: the lower bound
413      Value &lowerBound() { return _lb; }
414      ///The const version of \ref lowerBound()
415      const Value &lowerBound() const { return _lb; }
416      ///Reference to the upper bound.
417
418      ///\return
419      ///- \ref INF "INF": the constraint is upper unbounded.
420      ///- \ref NaN "NaN": upper bound has not been set.
421      ///- finite number: the upper bound
422      Value &upperBound() { return _ub; }
423      ///The const version of \ref upperBound()
424      const Value &upperBound() const { return _ub; }
425      ///Is the constraint lower bounded?
426      bool lowerBounded() const {
427        using namespace std;
428        return finite(_lb);
429      }
430      ///Is the constraint upper bounded?
431      bool upperBounded() const {
432        using namespace std;
433        return finite(_ub);
434      }
435    };
436   
437    ///Linear expression of rows
438   
439    ///This data structure represents a column of the matrix,
440    ///thas is it strores a linear expression of the dual variables
441    ///(\ref Row "Row"s).
442    ///
443    ///There are several ways to access and modify the contents of this
444    ///container.
445    ///- Its it fully compatible with \c std::map<Row,double>, so for expamle
446    ///if \c e is an DualExpr and \c v
447    ///and \c w are of type \ref Row, then you can
448    ///read and modify the coefficients like
449    ///these.
450    ///\code
451    ///e[v]=5;
452    ///e[v]+=12;
453    ///e.erase(v);
454    ///\endcode
455    ///or you can also iterate through its elements.
456    ///\code
457    ///double s=0;
458    ///for(LpSolverBase::DualExpr::iterator i=e.begin();i!=e.end();++i)
459    ///  s+=i->second;
460    ///\endcode
461    ///(This code computes the sum of all coefficients).
462    ///- Numbers (<tt>double</tt>'s)
463    ///and variables (\ref Row "Row"s) directly convert to an
464    ///\ref DualExpr and the usual linear operations are defined so 
465    ///\code
466    ///v+w
467    ///2*v-3.12*(v-w/2)
468    ///v*2.1+(3*v+(v*12+w)*3)/2
469    ///\endcode
470    ///are valid \ref DualExpr "DualExpr"essions.
471    ///The usual assignment operations are also defined.
472    ///\code
473    ///e=v+w;
474    ///e+=2*v-3.12*(v-w/2);
475    ///e*=3.4;
476    ///e/=5;
477    ///\endcode
478    ///
479    ///\sa Expr
480    ///
481    class DualExpr : public std::map<Row,Value>
482    {
483    public:
484      typedef LpSolverBase::Row Key;
485      typedef LpSolverBase::Value Value;
486     
487    protected:
488      typedef std::map<Row,Value> Base;
489     
490    public:
491      typedef True IsLinExpression;
492      ///\e
493      DualExpr() : Base() { }
494      ///\e
495      DualExpr(const Key &v) {
496        Base::insert(std::make_pair(v, 1));
497      }
498      ///\e
499      void set(const Key &v,const Value &c) {
500        Base::insert(std::make_pair(v, c));
501      }
502     
503      ///Removes the components with zero coefficient.
504      void simplify() {
505        for (Base::iterator i=Base::begin(); i!=Base::end();) {
506          Base::iterator j=i;
507          ++j;
508          if ((*i).second==0) Base::erase(i);
509          j=i;
510        }
511      }
512
513      ///Removes the coefficients closer to zero than \c tolerance.
514      void simplify(double &tolerance) {
515        for (Base::iterator i=Base::begin(); i!=Base::end();) {
516          Base::iterator j=i;
517          ++j;
518          if (std::fabs((*i).second)<tolerance) Base::erase(i);
519          j=i;
520        }
521      }
522
523
524      ///Sets all coefficients to 0.
525      void clear() {
526        Base::clear();
527      }
528
529      ///\e
530      DualExpr &operator+=(const DualExpr &e) {
531        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
532          (*this)[j->first]+=j->second;
533        return *this;
534      }
535      ///\e
536      DualExpr &operator-=(const DualExpr &e) {
537        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
538          (*this)[j->first]-=j->second;
539        return *this;
540      }
541      ///\e
542      DualExpr &operator*=(const Value &c) {
543        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
544          j->second*=c;
545        return *this;
546      }
547      ///\e
548      DualExpr &operator/=(const Value &c) {
549        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
550          j->second/=c;
551        return *this;
552      }
553    };
554   
555
556  protected:
557    _FixId rows;
558    _FixId cols;
559
560    //Abstract virtual functions
561    virtual LpSolverBase &_newLp() = 0;
562    virtual LpSolverBase &_copyLp(){
563      ///\todo This should be implemented here, too,  when we have problem retrieving routines. It can be overriden.
564
565      //Starting:
566      LpSolverBase & newlp(_newLp());
567      return newlp;
568      //return *(LpSolverBase*)0;
569    };
570
571    virtual int _addCol() = 0;
572    virtual int _addRow() = 0;
573    virtual void _eraseCol(int col) = 0;
574    virtual void _eraseRow(int row) = 0;
575    virtual void _setRowCoeffs(int i,
576                               int length,
577                               int  const * indices,
578                               Value  const * values ) = 0;
579    virtual void _setColCoeffs(int i,
580                               int length,
581                               int  const * indices,
582                               Value  const * values ) = 0;
583    virtual void _setCoeff(int row, int col, Value value) = 0;
584    virtual void _setColLowerBound(int i, Value value) = 0;
585    virtual void _setColUpperBound(int i, Value value) = 0;
586//     virtual void _setRowLowerBound(int i, Value value) = 0;
587//     virtual void _setRowUpperBound(int i, Value value) = 0;
588    virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
589    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
590    virtual void _clearObj()=0;
591//     virtual void _setObj(int length,
592//                          int  const * indices,
593//                          Value  const * values ) = 0;
594    virtual SolveExitStatus _solve() = 0;
595    virtual Value _getPrimal(int i) = 0;
596    virtual Value _getDual(int i) = 0;
597    virtual Value _getPrimalValue() = 0;
598    virtual bool _isBasicCol(int i) = 0;
599    virtual SolutionStatus _getPrimalStatus() = 0;
600    virtual SolutionStatus _getDualStatus() = 0;
601    ///\todo This could be implemented here, too, using _getPrimalStatus() and
602    ///_getDualStatus()
603    virtual ProblemTypes _getProblemType() = 0;
604
605    virtual void _setMax() = 0;
606    virtual void _setMin() = 0;
607   
608    //Own protected stuff
609   
610    //Constant component of the objective function
611    Value obj_const_comp;
612   
613
614
615   
616  public:
617
618    ///\e
619    LpSolverBase() : obj_const_comp(0) {}
620
621    ///\e
622    virtual ~LpSolverBase() {}
623
624    ///Creates a new LP problem
625    LpSolverBase &newLp() {return _newLp();}
626    ///Makes a copy of the LP problem
627    LpSolverBase &copyLp() {return _copyLp();}
628   
629    ///\name Build up and modify the LP
630
631    ///@{
632
633    ///Add a new empty column (i.e a new variable) to the LP
634    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
635
636    ///\brief Adds several new columns
637    ///(i.e a variables) at once
638    ///
639    ///This magic function takes a container as its argument
640    ///and fills its elements
641    ///with new columns (i.e. variables)
642    ///\param t can be
643    ///- a standard STL compatible iterable container with
644    ///\ref Col as its \c values_type
645    ///like
646    ///\code
647    ///std::vector<LpSolverBase::Col>
648    ///std::list<LpSolverBase::Col>
649    ///\endcode
650    ///- a standard STL compatible iterable container with
651    ///\ref Col as its \c mapped_type
652    ///like
653    ///\code
654    ///std::map<AnyType,LpSolverBase::Col>
655    ///\endcode
656    ///- an iterable lemon \ref concept::WriteMap "write map" like
657    ///\code
658    ///ListGraph::NodeMap<LpSolverBase::Col>
659    ///ListGraph::EdgeMap<LpSolverBase::Col>
660    ///\endcode
661    ///\return The number of the created column.
662#ifdef DOXYGEN
663    template<class T>
664    int addColSet(T &t) { return 0;}
665#else
666    template<class T>
667    typename enable_if<typename T::value_type::LpSolverCol,int>::type
668    addColSet(T &t,dummy<0> = 0) {
669      int s=0;
670      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
671      return s;
672    }
673    template<class T>
674    typename enable_if<typename T::value_type::second_type::LpSolverCol,
675                       int>::type
676    addColSet(T &t,dummy<1> = 1) {
677      int s=0;
678      for(typename T::iterator i=t.begin();i!=t.end();++i) {
679        i->second=addCol();
680        s++;
681      }
682      return s;
683    }
684    template<class T>
685    typename enable_if<typename T::MapIt::Value::LpSolverCol,
686                       int>::type
687    addColSet(T &t,dummy<2> = 2) {
688      int s=0;
689      for(typename T::MapIt i(t); i!=INVALID; ++i)
690        {
691          i.set(addCol());
692          s++;
693        }
694      return s;
695    }
696#endif
697
698    ///Set a column (i.e a dual constraint) of the LP
699
700    ///\param c is the column to be modified
701    ///\param e is a dual linear expression (see \ref DualExpr)
702    ///\bug This is a temporary function. The interface will change to
703    ///a better one.
704    void setCol(Col c,const DualExpr &e) {
705      std::vector<int> indices;
706      std::vector<Value> values;
707      indices.push_back(0);
708      values.push_back(0);
709      for(DualExpr::const_iterator i=e.begin(); i!=e.end(); ++i)
710        if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
711          indices.push_back(rows.floatingId((*i).first.id));
712          values.push_back((*i).second);
713        }
714      _setColCoeffs(cols.floatingId(c.id),indices.size()-1,
715                    &indices[0],&values[0]);
716    }
717
718    ///Add a new column to the LP
719
720    ///\param e is a dual linear expression (see \ref DualExpr)
721    ///\param obj is the corresponding component of the objective
722    ///function. It is 0 by default.
723    ///\return The created column.
724    ///\bug This is a temportary function. The interface will change to
725    ///a better one.
726    Col addCol(const DualExpr &e, Value obj=0) {
727      Col c=addCol();
728      setCol(c,e);
729      objCoeff(c,obj);
730      return c;
731    }
732
733    ///Add a new empty row (i.e a new constraint) to the LP
734
735    ///This function adds a new empty row (i.e a new constraint) to the LP.
736    ///\return The created row
737    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
738
739    ///\brief Add several new rows
740    ///(i.e a constraints) at once
741    ///
742    ///This magic function takes a container as its argument
743    ///and fills its elements
744    ///with new row (i.e. variables)
745    ///\param t can be
746    ///- a standard STL compatible iterable container with
747    ///\ref Row as its \c values_type
748    ///like
749    ///\code
750    ///std::vector<LpSolverBase::Row>
751    ///std::list<LpSolverBase::Row>
752    ///\endcode
753    ///- a standard STL compatible iterable container with
754    ///\ref Row as its \c mapped_type
755    ///like
756    ///\code
757    ///std::map<AnyType,LpSolverBase::Row>
758    ///\endcode
759    ///- an iterable lemon \ref concept::WriteMap "write map" like
760    ///\code
761    ///ListGraph::NodeMap<LpSolverBase::Row>
762    ///ListGraph::EdgeMap<LpSolverBase::Row>
763    ///\endcode
764    ///\return The number of rows created.
765#ifdef DOXYGEN
766    template<class T>
767    int addRowSet(T &t) { return 0;}
768#else
769    template<class T>
770    typename enable_if<typename T::value_type::LpSolverRow,int>::type
771    addRowSet(T &t,dummy<0> = 0) {
772      int s=0;
773      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
774      return s;
775    }
776    template<class T>
777    typename enable_if<typename T::value_type::second_type::LpSolverRow,
778                       int>::type
779    addRowSet(T &t,dummy<1> = 1) {
780      int s=0;
781      for(typename T::iterator i=t.begin();i!=t.end();++i) {
782        i->second=addRow();
783        s++;
784      }
785      return s;
786    }
787    template<class T>
788    typename enable_if<typename T::MapIt::Value::LpSolverRow,
789                       int>::type
790    addRowSet(T &t,dummy<2> = 2) {
791      int s=0;
792      for(typename T::MapIt i(t); i!=INVALID; ++i)
793        {
794          i.set(addRow());
795          s++;
796        }
797      return s;
798    }
799#endif
800
801    ///Set a row (i.e a constraint) of the LP
802
803    ///\param r is the row to be modified
804    ///\param l is lower bound (-\ref INF means no bound)
805    ///\param e is a linear expression (see \ref Expr)
806    ///\param u is the upper bound (\ref INF means no bound)
807    ///\bug This is a temportary function. The interface will change to
808    ///a better one.
809    ///\todo Option to control whether a constraint with a single variable is
810    ///added or not.
811    void setRow(Row r, Value l,const Expr &e, Value u) {
812      std::vector<int> indices;
813      std::vector<Value> values;
814      indices.push_back(0);
815      values.push_back(0);
816      for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
817        if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
818          indices.push_back(cols.floatingId((*i).first.id));
819          values.push_back((*i).second);
820        }
821      _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
822                    &indices[0],&values[0]);
823//       _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
824//       _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
825       _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp());
826    }
827
828    ///Set a row (i.e a constraint) of the LP
829
830    ///\param r is the row to be modified
831    ///\param c is a linear expression (see \ref Constr)
832    void setRow(Row r, const Constr &c) {
833      setRow(r,
834             c.lowerBounded()?c.lowerBound():-INF,
835             c.expr(),
836             c.upperBounded()?c.upperBound():INF);
837    }
838
839    ///Add a new row (i.e a new constraint) to the LP
840
841    ///\param l is the lower bound (-\ref INF means no bound)
842    ///\param e is a linear expression (see \ref Expr)
843    ///\param u is the upper bound (\ref INF means no bound)
844    ///\return The created row.
845    ///\bug This is a temportary function. The interface will change to
846    ///a better one.
847    Row addRow(Value l,const Expr &e, Value u) {
848      Row r=addRow();
849      setRow(r,l,e,u);
850      return r;
851    }
852
853    ///Add a new row (i.e a new constraint) to the LP
854
855    ///\param c is a linear expression (see \ref Constr)
856    ///\return The created row.
857    Row addRow(const Constr &c) {
858      Row r=addRow();
859      setRow(r,c);
860      return r;
861    }
862    ///Erase a coloumn (i.e a variable) from the LP
863
864    ///\param c is the coloumn to be deleted
865    ///\todo Please check this
866    void eraseCol(Col c) {
867      _eraseCol(cols.floatingId(c.id));
868      cols.erase(c.id);
869    }
870    ///Erase a  row (i.e a constraint) from the LP
871
872    ///\param r is the row to be deleted
873    ///\todo Please check this
874    void eraseRow(Row r) {
875      _eraseRow(rows.floatingId(r.id));
876      rows.erase(r.id);
877    }
878
879    ///Set an element of the coefficient matrix of the LP
880
881    ///\param r is the row of the element to be modified
882    ///\param c is the coloumn of the element to be modified
883    ///\param val is the new value of the coefficient
884    void setCoeff(Row r, Col c, Value val){
885      _setCoeff(rows.floatingId(r.id),cols.floatingId(c.id), val);
886    }
887
888    /// Set the lower bound of a column (i.e a variable)
889
890    /// The upper bound of a variable (column) has to be given by an
891    /// extended number of type Value, i.e. a finite number of type
892    /// Value or -\ref INF.
893    void colLowerBound(Col c, Value value) {
894      _setColLowerBound(cols.floatingId(c.id),value);
895    }
896    /// Set the upper bound of a column (i.e a variable)
897
898    /// The upper bound of a variable (column) has to be given by an
899    /// extended number of type Value, i.e. a finite number of type
900    /// Value or \ref INF.
901    void colUpperBound(Col c, Value value) {
902      _setColUpperBound(cols.floatingId(c.id),value);
903    };
904    /// Set the lower and the upper bounds of a column (i.e a variable)
905
906    /// The lower and the upper bounds of
907    /// a variable (column) have to be given by an
908    /// extended number of type Value, i.e. a finite number of type
909    /// Value, -\ref INF or \ref INF.
910    void colBounds(Col c, Value lower, Value upper) {
911      _setColLowerBound(cols.floatingId(c.id),lower);
912      _setColUpperBound(cols.floatingId(c.id),upper);
913    }
914   
915//     /// Set the lower bound of a row (i.e a constraint)
916
917//     /// The lower bound of a linear expression (row) has to be given by an
918//     /// extended number of type Value, i.e. a finite number of type
919//     /// Value or -\ref INF.
920//     void rowLowerBound(Row r, Value value) {
921//       _setRowLowerBound(rows.floatingId(r.id),value);
922//     };
923//     /// Set the upper bound of a row (i.e a constraint)
924
925//     /// The upper bound of a linear expression (row) has to be given by an
926//     /// extended number of type Value, i.e. a finite number of type
927//     /// Value or \ref INF.
928//     void rowUpperBound(Row r, Value value) {
929//       _setRowUpperBound(rows.floatingId(r.id),value);
930//     };
931
932    /// Set the lower and the upper bounds of a row (i.e a constraint)
933
934    /// The lower and the upper bounds of
935    /// a constraint (row) have to be given by an
936    /// extended number of type Value, i.e. a finite number of type
937    /// Value, -\ref INF or \ref INF.
938    void rowBounds(Row c, Value lower, Value upper) {
939      _setRowBounds(rows.floatingId(c.id),lower, upper);
940      // _setRowUpperBound(rows.floatingId(c.id),upper);
941    }
942   
943    ///Set an element of the objective function
944    void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
945    ///Set the objective function
946   
947    ///\param e is a linear expression of type \ref Expr.
948    void setObj(Expr e) {
949      _clearObj();
950      for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
951        objCoeff((*i).first,(*i).second);
952      obj_const_comp=e.constComp();
953    }
954
955    ///Maximize
956    void max() { _setMax(); }
957    ///Minimize
958    void min() { _setMin(); }
959
960   
961    ///@}
962
963
964    ///\name Solve the LP
965
966    ///@{
967
968    ///\e Solve the LP problem at hand
969    ///
970    ///\return The result of the optimization procedure. Possible values and their meanings can be found in the documentation of \ref SolveExitStatus.
971    ///
972    ///\todo Which method is used to solve the problem
973    SolveExitStatus solve() { return _solve(); }
974   
975    ///@}
976   
977    ///\name Obtain the solution
978
979    ///@{
980
981    /// The status of the primal problem (the original LP problem)
982    SolutionStatus primalStatus() {
983      return _getPrimalStatus();
984    }
985
986    /// The status of the dual (of the original LP) problem
987    SolutionStatus dualStatus() {
988      return _getDualStatus();
989    }
990
991    ///The type of the original LP problem
992    ProblemTypes problemType() {
993      return _getProblemType();
994    }
995
996    ///\e
997    Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
998
999    ///\e
1000    Value dual(Row r) { return _getDual(rows.floatingId(r.id)); }
1001
1002    ///\e
1003    bool isBasicCol(Col c) { return _isBasicCol(cols.floatingId(c.id)); }
1004
1005    ///\e
1006
1007    ///\return
1008    ///- \ref INF or -\ref INF means either infeasibility or unboundedness
1009    /// of the primal problem, depending on whether we minimize or maximize.
1010    ///- \ref NaN if no primal solution is found.
1011    ///- The (finite) objective value if an optimal solution is found.
1012    Value primalValue() { return _getPrimalValue()+obj_const_comp;}
1013    ///@}
1014   
1015  }; 
1016
1017  ///\e
1018 
1019  ///\relates LpSolverBase::Expr
1020  ///
1021  inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
1022                                      const LpSolverBase::Expr &b)
1023  {
1024    LpSolverBase::Expr tmp(a);
1025    tmp+=b;
1026    return tmp;
1027  }
1028  ///\e
1029 
1030  ///\relates LpSolverBase::Expr
1031  ///
1032  inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
1033                                      const LpSolverBase::Expr &b)
1034  {
1035    LpSolverBase::Expr tmp(a);
1036    tmp-=b;
1037    return tmp;
1038  }
1039  ///\e
1040 
1041  ///\relates LpSolverBase::Expr
1042  ///
1043  inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
1044                                      const LpSolverBase::Value &b)
1045  {
1046    LpSolverBase::Expr tmp(a);
1047    tmp*=b;
1048    return tmp;
1049  }
1050 
1051  ///\e
1052 
1053  ///\relates LpSolverBase::Expr
1054  ///
1055  inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
1056                                      const LpSolverBase::Expr &b)
1057  {
1058    LpSolverBase::Expr tmp(b);
1059    tmp*=a;
1060    return tmp;
1061  }
1062  ///\e
1063 
1064  ///\relates LpSolverBase::Expr
1065  ///
1066  inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
1067                                      const LpSolverBase::Value &b)
1068  {
1069    LpSolverBase::Expr tmp(a);
1070    tmp/=b;
1071    return tmp;
1072  }
1073 
1074  ///\e
1075 
1076  ///\relates LpSolverBase::Constr
1077  ///
1078  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
1079                                         const LpSolverBase::Expr &f)
1080  {
1081    return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
1082  }
1083
1084  ///\e
1085 
1086  ///\relates LpSolverBase::Constr
1087  ///
1088  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
1089                                         const LpSolverBase::Expr &f)
1090  {
1091    return LpSolverBase::Constr(e,f);
1092  }
1093
1094  ///\e
1095 
1096  ///\relates LpSolverBase::Constr
1097  ///
1098  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
1099                                         const LpSolverBase::Value &f)
1100  {
1101    return LpSolverBase::Constr(e,f);
1102  }
1103
1104  ///\e
1105 
1106  ///\relates LpSolverBase::Constr
1107  ///
1108  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
1109                                         const LpSolverBase::Expr &f)
1110  {
1111    return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
1112  }
1113
1114
1115  ///\e
1116 
1117  ///\relates LpSolverBase::Constr
1118  ///
1119  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
1120                                         const LpSolverBase::Expr &f)
1121  {
1122    return LpSolverBase::Constr(f,e);
1123  }
1124
1125
1126  ///\e
1127 
1128  ///\relates LpSolverBase::Constr
1129  ///
1130  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
1131                                         const LpSolverBase::Value &f)
1132  {
1133    return LpSolverBase::Constr(f,e);
1134  }
1135
1136  ///\e
1137 
1138  ///\relates LpSolverBase::Constr
1139  ///
1140  inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
1141                                         const LpSolverBase::Expr &f)
1142  {
1143    return LpSolverBase::Constr(0,e-f,0);
1144  }
1145
1146  ///\e
1147 
1148  ///\relates LpSolverBase::Constr
1149  ///
1150  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
1151                                         const LpSolverBase::Constr&c)
1152  {
1153    LpSolverBase::Constr tmp(c);
1154    ///\todo Create an own exception type.
1155    if(!isnan(tmp.lowerBound())) throw LogicError();
1156    else tmp.lowerBound()=n;
1157    return tmp;
1158  }
1159  ///\e
1160 
1161  ///\relates LpSolverBase::Constr
1162  ///
1163  inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
1164                                         const LpSolverBase::Value &n)
1165  {
1166    LpSolverBase::Constr tmp(c);
1167    ///\todo Create an own exception type.
1168    if(!isnan(tmp.upperBound())) throw LogicError();
1169    else tmp.upperBound()=n;
1170    return tmp;
1171  }
1172
1173  ///\e
1174 
1175  ///\relates LpSolverBase::Constr
1176  ///
1177  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
1178                                         const LpSolverBase::Constr&c)
1179  {
1180    LpSolverBase::Constr tmp(c);
1181    ///\todo Create an own exception type.
1182    if(!isnan(tmp.upperBound())) throw LogicError();
1183    else tmp.upperBound()=n;
1184    return tmp;
1185  }
1186  ///\e
1187 
1188  ///\relates LpSolverBase::Constr
1189  ///
1190  inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
1191                                         const LpSolverBase::Value &n)
1192  {
1193    LpSolverBase::Constr tmp(c);
1194    ///\todo Create an own exception type.
1195    if(!isnan(tmp.lowerBound())) throw LogicError();
1196    else tmp.lowerBound()=n;
1197    return tmp;
1198  }
1199
1200  ///\e
1201 
1202  ///\relates LpSolverBase::DualExpr
1203  ///
1204  inline LpSolverBase::DualExpr operator+(const LpSolverBase::DualExpr &a,
1205                                      const LpSolverBase::DualExpr &b)
1206  {
1207    LpSolverBase::DualExpr tmp(a);
1208    tmp+=b;
1209    return tmp;
1210  }
1211  ///\e
1212 
1213  ///\relates LpSolverBase::DualExpr
1214  ///
1215  inline LpSolverBase::DualExpr operator-(const LpSolverBase::DualExpr &a,
1216                                      const LpSolverBase::DualExpr &b)
1217  {
1218    LpSolverBase::DualExpr tmp(a);
1219    tmp-=b;
1220    return tmp;
1221  }
1222  ///\e
1223 
1224  ///\relates LpSolverBase::DualExpr
1225  ///
1226  inline LpSolverBase::DualExpr operator*(const LpSolverBase::DualExpr &a,
1227                                      const LpSolverBase::Value &b)
1228  {
1229    LpSolverBase::DualExpr tmp(a);
1230    tmp*=b;
1231    return tmp;
1232  }
1233 
1234  ///\e
1235 
1236  ///\relates LpSolverBase::DualExpr
1237  ///
1238  inline LpSolverBase::DualExpr operator*(const LpSolverBase::Value &a,
1239                                      const LpSolverBase::DualExpr &b)
1240  {
1241    LpSolverBase::DualExpr tmp(b);
1242    tmp*=a;
1243    return tmp;
1244  }
1245  ///\e
1246 
1247  ///\relates LpSolverBase::DualExpr
1248  ///
1249  inline LpSolverBase::DualExpr operator/(const LpSolverBase::DualExpr &a,
1250                                      const LpSolverBase::Value &b)
1251  {
1252    LpSolverBase::DualExpr tmp(a);
1253    tmp/=b;
1254    return tmp;
1255  }
1256 
1257
1258} //namespace lemon
1259
1260#endif //LEMON_LP_BASE_H
Note: See TracBrowser for help on using the repository browser.