COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_base.h @ 2312:07e46cbb7d85

Last change on this file since 2312:07e46cbb7d85 was 2312:07e46cbb7d85, checked in by Balazs Dezso, 17 years ago

modified _setColCoeff and _setRowCoeff parameters
const simplify() for expressions

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