COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lp_base.h @ 1323:3aaadfb7de3d

Last change on this file since 1323:3aaadfb7de3d was 1323:3aaadfb7de3d, checked in by Alpar Juttner, 20 years ago

The case when the objective function contains a const component is handled
correctly.

File size: 22.7 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/lp_base.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, 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<math.h>
24
25#include<lemon/utility.h>
26#include<lemon/error.h>
27#include<lemon/invalid.h>
28
29//#include"lin_expr.h"
30
31///\file
32///\brief The interface of the LP solver interface.
33namespace lemon {
34 
35  ///Internal data structure to convert floating id's to fix one's
36   
37  ///\todo This might be implemented to be also usable in other places.
38  class _FixId
39  {
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) {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) { 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  class LpSolverBase {
104
105  public:
106
107    ///\e
108    enum SolveExitStatus {
109      ///\e
110      SOLVED = 0,
111      ///\e
112      UNSOLVED = 1
113    };
114     
115    ///\e
116    enum SolutionStatus {
117      ///Feasible solution has'n been found (but may exist).
118
119      ///\todo NOTFOUND might be a better name.
120      ///
121      UNDEFINED = 0,
122      ///The problem has no feasible solution
123      INFEASIBLE = 1,
124      ///Feasible solution found
125      FEASIBLE = 2,
126      ///Optimal solution exists and found
127      OPTIMAL = 3,
128      ///The cost function is unbounded
129
130      ///\todo Give a feasible solution and an infinite ray (and the
131      ///corresponding bases)
132      INFINITE = 4
133    };
134     
135    ///The floating point type used by the solver
136    typedef double Value;
137    ///The infinity constant
138    static const Value INF;
139    ///The not a number constant
140    static const Value NaN;
141   
142    ///Refer to a column of the LP.
143
144    ///This type is used to refer to a column of the LP.
145    ///
146    ///Its value remains valid and correct even after the addition or erase of
147    ///other columns.
148    ///
149    ///\todo Document what can one do with a Col (INVALID, comparing,
150    ///it is similar to Node/Edge)
151    class Col {
152    protected:
153      int id;
154      friend class LpSolverBase;
155    public:
156      typedef Value ExprValue;
157      typedef True LpSolverCol;
158      Col() {}
159      Col(const Invalid&) : id(-1) {}
160      bool operator<(Col c) const  {return id<c.id;}
161      bool operator==(Col c) const  {return id==c.id;}
162      bool operator!=(Col c) const  {return id==c.id;}
163    };
164
165    ///Refer to a row of the LP.
166
167    ///This type is used to refer to a row of the LP.
168    ///
169    ///Its value remains valid and correct even after the addition or erase of
170    ///other rows.
171    ///
172    ///\todo Document what can one do with a Row (INVALID, comparing,
173    ///it is similar to Node/Edge)
174    class Row {
175    protected:
176      int id;
177      friend class LpSolverBase;
178    public:
179      typedef Value ExprValue;
180      typedef True LpSolverRow;
181      Row() {}
182      Row(const Invalid&) : id(-1) {}
183      typedef True LpSolverRow;
184      bool operator<(Row c) const  {return id<c.id;}
185      bool operator==(Row c) const  {return id==c.id;}
186      bool operator!=(Row c) const  {return id==c.id;}
187   };
188   
189    ///Linear expression of variables and a constant component
190   
191    ///This data structure strores a linear expression of the variables
192    ///(\ref Col "Col"s) and also has a constant component.
193    ///
194    ///There are several ways to access and modify the contents of this
195    ///container.
196    ///- Its it fully compatible with \c std::map<Col,double>, so for expamle
197    ///if \c e is an Expr and \c v and \c w are of type \ref Col then you can
198    ///read and modify the coefficients like
199    ///these.
200    ///\code
201    ///e[v]=5;
202    ///e[v]+=12;
203    ///e.erase(v);
204    ///\endcode
205    ///or you can also iterate through its elements.
206    ///\code
207    ///double s=0;
208    ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i)
209    ///  s+=i->second;
210    ///\endcode
211    ///(This code computes the sum of all coefficients).
212    ///- Numbers (<tt>double</tt>'s)
213    ///and variables (\ref Col "Col"s) directly convert to an
214    ///\ref Expr and the usual linear operations are defined so 
215    ///\code
216    ///v+w
217    ///2*v-3.12*(v-w/2)+2
218    ///v*2.1+(3*v+(v*12+w+6)*3)/2
219    ///\endcode
220    ///are valid expressions. The usual assignment operations are also defined.
221    ///\code
222    ///e=v+w;
223    ///e+=2*v-3.12*(v-w/2)+2;
224    ///e*=3.4;
225    ///e/=5;
226    ///\endcode
227    ///- The constant member can be set and read by \ref constComp()
228    ///\code
229    ///e.constComp()=12;
230    ///double c=e.constComp();
231    ///\endcode
232    ///
233    ///\note that \ref clear() not only sets all coefficients to 0 but also
234    ///clears the constant components.
235    class Expr : public std::map<Col,Value>
236    {
237    public:
238      typedef LpSolverBase::Col Key;
239      typedef LpSolverBase::Value Value;
240     
241    protected:
242      typedef std::map<Col,Value> Base;
243     
244      Value const_comp;
245  public:
246      typedef True IsLinExpression;
247      ///\e
248      Expr() : Base(), const_comp(0) { }
249      ///\e
250      Expr(const Key &v) : const_comp(0) {
251        Base::insert(std::make_pair(v, 1));
252      }
253      ///\e
254      Expr(const Value &v) : const_comp(v) {}
255      ///\e
256      void set(const Key &v,const Value &c) {
257        Base::insert(std::make_pair(v, c));
258      }
259      ///\e
260      Value &constComp() { return const_comp; }
261      ///\e
262      const Value &constComp() const { return const_comp; }
263     
264      ///Removes the components with zero coefficient.
265      void simplify() {
266        for (Base::iterator i=Base::begin(); i!=Base::end();) {
267          Base::iterator j=i;
268          ++j;
269          if ((*i).second==0) Base::erase(i);
270          j=i;
271        }
272      }
273
274      ///Sets all coefficients and the constant component to 0.
275      void clear() {
276        Base::clear();
277        const_comp=0;
278      }
279
280      ///\e
281      Expr &operator+=(const Expr &e) {
282        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
283          (*this)[j->first]+=j->second;
284        ///\todo it might be speeded up using "hints"
285        const_comp+=e.const_comp;
286        return *this;
287      }
288      ///\e
289      Expr &operator-=(const Expr &e) {
290        for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
291          (*this)[j->first]-=j->second;
292        const_comp-=e.const_comp;
293        return *this;
294      }
295      ///\e
296      Expr &operator*=(const Value &c) {
297        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
298          j->second*=c;
299        const_comp*=c;
300        return *this;
301      }
302      ///\e
303      Expr &operator/=(const Value &c) {
304        for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
305          j->second/=c;
306        const_comp/=c;
307        return *this;
308      }
309    };
310   
311    ///Linear constraint
312    //typedef LinConstr<Expr> Constr;
313    class Constr
314    {
315    public:
316      typedef LpSolverBase::Expr Expr;
317      typedef Expr::Key Key;
318      typedef Expr::Value Value;
319     
320      static const Value INF;
321      static const Value NaN;
322      //     static const Value INF=0;
323      //     static const Value NaN=1;
324     
325    protected:
326      Expr _expr;
327      Value _lb,_ub;
328    public:
329      ///\e
330      Constr() : _expr(), _lb(NaN), _ub(NaN) {}
331      ///\e
332      Constr(Value lb,const Expr &e,Value ub) :
333        _expr(e), _lb(lb), _ub(ub) {}
334      ///\e
335      Constr(const Expr &e,Value ub) :
336        _expr(e), _lb(NaN), _ub(ub) {}
337      ///\e
338      Constr(Value lb,const Expr &e) :
339        _expr(e), _lb(lb), _ub(NaN) {}
340      ///\e
341      Constr(const Expr &e) :
342        _expr(e), _lb(NaN), _ub(NaN) {}
343      ///\e
344      void clear()
345      {
346        _expr.clear();
347        _lb=_ub=NaN;
348      }
349      ///\e
350      Expr &expr() { return _expr; }
351      ///\e
352      const Expr &expr() const { return _expr; }
353      ///\e
354      Value &lowerBound() { return _lb; }
355      ///\e
356      const Value &lowerBound() const { return _lb; }
357      ///\e
358      Value &upperBound() { return _ub; }
359      ///\e
360      const Value &upperBound() const { return _ub; }
361      ///\e
362      bool lowerBounded() const {
363        using namespace std;
364        return isfinite(_lb);
365      }
366      ///\e
367      bool upperBounded() const {
368        using namespace std;
369        return isfinite(_ub);
370      }
371    };
372   
373
374  protected:
375    _FixId rows;
376    _FixId cols;
377
378    //Abstract virtual functions
379    virtual int _addCol() = 0;
380    virtual int _addRow() = 0;
381    virtual void _setRowCoeffs(int i,
382                               int length,
383                               int  const * indices,
384                               Value  const * values ) = 0;
385    virtual void _setColCoeffs(int i,
386                               int length,
387                               int  const * indices,
388                               Value  const * values ) = 0;
389    virtual void _setColLowerBound(int i, Value value) = 0;
390    virtual void _setColUpperBound(int i, Value value) = 0;
391    virtual void _setRowLowerBound(int i, Value value) = 0;
392    virtual void _setRowUpperBound(int i, Value value) = 0;
393    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
394    virtual SolveExitStatus _solve() = 0;
395    virtual Value _getPrimal(int i) = 0;
396    virtual Value _getPrimalValue() = 0;
397    virtual SolutionStatus _getPrimalStatus() = 0;
398    virtual void _setMax() = 0;
399    virtual void _setMin() = 0;
400   
401    //Own protected stuff
402   
403    //Constant component of the objective function
404    Value obj_const_comp;
405   
406    ///\e
407   
408    ///\bug Unimplemented
409    void clearObj() {}
410   
411  public:
412
413    ///\e
414    LpSolverBase() : obj_const_comp(0) {}
415
416    ///\e
417    virtual ~LpSolverBase() {}
418
419    ///\name Build up and modify of the LP
420
421    ///@{
422
423    ///Add a new empty column (i.e a new variable) to the LP
424    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
425
426    ///\brief Adds several new columns
427    ///(i.e a variables) at once
428    ///
429    ///This magic function takes a container as its argument
430    ///and fills its elements
431    ///with new columns (i.e. variables)
432    ///\param t can be
433    ///- a standard STL compatible iterable container with
434    ///\ref Col as its \c values_type
435    ///like
436    ///\code
437    ///std::vector<LpSolverBase::Col>
438    ///std::list<LpSolverBase::Col>
439    ///\endcode
440    ///- a standard STL compatible iterable container with
441    ///\ref Col as its \c mapped_type
442    ///like
443    ///\code
444    ///std::map<AnyStatus,LpSolverBase::Col>
445    ///\endcode
446    ///- an iterable lemon \ref concept::WriteMap "write map" like
447    ///\code
448    ///ListGraph::NodeMap<LpSolverBase::Col>
449    ///ListGraph::EdgeMap<LpSolverBase::Col>
450    ///\endcode
451    ///\return The number of the created column.
452    ///\bug Iterable nodemap hasn't been implemented yet.
453#ifdef DOXYGEN
454    template<class T>
455    int addColSet(T &t) { return 0;}
456#else
457    template<class T>
458    typename enable_if<typename T::value_type::LpSolverCol,int>::type
459    addColSet(T &t,dummy<0> = 0) {
460      int s=0;
461      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
462      return s;
463    }
464    template<class T>
465    typename enable_if<typename T::value_type::second_type::LpSolverCol,
466                       int>::type
467    addColSet(T &t,dummy<1> = 1) {
468      int s=0;
469      for(typename T::iterator i=t.begin();i!=t.end();++i) {
470        i->second=addCol();
471        s++;
472      }
473      return s;
474    }
475    template<class T>
476    typename enable_if<typename T::ValueSet::value_type::LpSolverCol,
477                       int>::type
478    addColSet(T &t,dummy<2> = 2) {
479      ///\bug <tt>return addColSet(t.valueSet());</tt> should also work.
480      int s=0;
481      for(typename T::ValueSet::iterator i=t.valueSet().begin();
482          i!=t.valueSet().end();
483          ++i)
484        {
485          *i=addCol();
486          s++;
487        }
488      return s;
489    }
490#endif
491
492    ///Add a new empty row (i.e a new constaint) to the LP
493
494    ///This function adds a new empty row (i.e a new constaint) to the LP.
495    ///\return The created row
496    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
497
498    ///Set a row (i.e a constaint) of the LP
499
500    ///\param r is the row to be modified
501    ///\param l is lower bound (-\ref INF means no bound)
502    ///\param e is a linear expression (see \ref Expr)
503    ///\param u is the upper bound (\ref INF means no bound)
504    ///\bug This is a temportary function. The interface will change to
505    ///a better one.
506    void setRow(Row r, Value l,const Expr &e, Value u) {
507      std::vector<int> indices;
508      std::vector<Value> values;
509      indices.push_back(0);
510      values.push_back(0);
511      for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
512        if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
513          indices.push_back(cols.floatingId((*i).first.id));
514          values.push_back((*i).second);
515        }
516      _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
517                    &indices[0],&values[0]);
518      _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
519      _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
520    }
521
522    ///Set a row (i.e a constaint) of the LP
523
524    ///\param r is the row to be modified
525    ///\param c is a linear expression (see \ref Constr)
526    void setRow(Row r, const Constr &c) {
527      setRow(r,
528             c.lowerBounded()?c.lowerBound():-INF,
529             c.expr(),
530             c.upperBounded()?c.upperBound():INF);
531    }
532
533    ///Add a new row (i.e a new constaint) to the LP
534
535    ///\param l is the lower bound (-\ref INF means no bound)
536    ///\param e is a linear expression (see \ref Expr)
537    ///\param u is the upper bound (\ref INF means no bound)
538    ///\return The created row.
539    ///\bug This is a temportary function. The interface will change to
540    ///a better one.
541    Row addRow(Value l,const Expr &e, Value u) {
542      Row r=addRow();
543      setRow(r,l,e,u);
544      return r;
545    }
546
547    ///Add a new row (i.e a new constaint) to the LP
548
549    ///\param c is a linear expression (see \ref Constr)
550    ///\return The created row.
551    Row addRow(const Constr &c) {
552      Row r=addRow();
553      setRow(r,c);
554      return r;
555    }
556
557    /// Set the lower bound of a column (i.e a variable)
558
559    /// The upper bound of a variable (column) has to be given by an
560    /// extended number of type Value, i.e. a finite number of type
561    /// Value or -\ref INF.
562    void colLowerBound(Col c, Value value) {
563      _setColLowerBound(cols.floatingId(c.id),value);
564    }
565    /// Set the upper bound of a column (i.e a variable)
566
567    /// The upper bound of a variable (column) has to be given by an
568    /// extended number of type Value, i.e. a finite number of type
569    /// Value or \ref INF.
570    void colUpperBound(Col c, Value value) {
571      _setColUpperBound(cols.floatingId(c.id),value);
572    };
573    /// Set the lower and the upper bounds of a column (i.e a variable)
574
575    /// The lower and the upper bounds of
576    /// a variable (column) have to be given by an
577    /// extended number of type Value, i.e. a finite number of type
578    /// Value, -\ref INF or \ref INF.
579    void colBounds(Col c, Value lower, Value upper) {
580      _setColLowerBound(cols.floatingId(c.id),lower);
581      _setColUpperBound(cols.floatingId(c.id),upper);
582    }
583   
584    /// Set the lower bound of a row (i.e a constraint)
585
586    /// The lower bound of a linear expression (row) has to be given by an
587    /// extended number of type Value, i.e. a finite number of type
588    /// Value or -\ref INF.
589    void rowLowerBound(Row r, Value value) {
590      _setRowLowerBound(rows.floatingId(r.id),value);
591    };
592    /// Set the upper bound of a row (i.e a constraint)
593
594    /// The upper bound of a linear expression (row) has to be given by an
595    /// extended number of type Value, i.e. a finite number of type
596    /// Value or \ref INF.
597    void rowUpperBound(Row r, Value value) {
598      _setRowUpperBound(rows.floatingId(r.id),value);
599    };
600    /// Set the lower and the upper bounds of a row (i.e a variable)
601
602    /// The lower and the upper bounds of
603    /// a constraint (row) have to be given by an
604    /// extended number of type Value, i.e. a finite number of type
605    /// Value, -\ref INF or \ref INF.
606    void rowBounds(Row c, Value lower, Value upper) {
607      _setRowLowerBound(rows.floatingId(c.id),lower);
608      _setRowUpperBound(rows.floatingId(c.id),upper);
609    }
610   
611    ///Set an element of the objective function
612    void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
613    ///Set the objective function
614   
615    ///\param e is a linear expression of type \ref Expr.
616    ///\bug The previous objective function is not cleared!
617    void setObj(Expr e) {
618      clearObj();
619      for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
620        objCoeff((*i).first,(*i).second);
621      obj_const_comp=e.constComp();
622    }
623
624    ///Maximize
625    void max() { _setMax(); }
626    ///Minimize
627    void min() { _setMin(); }
628
629   
630    ///@}
631
632
633    ///\name Solve the LP
634
635    ///@{
636
637    ///\e
638    SolveExitStatus solve() { return _solve(); }
639   
640    ///@}
641   
642    ///\name Obtain the solution
643
644    ///@{
645
646    ///\e
647    SolutionStatus primalStatus() {
648      return _getPrimalStatus();
649    }
650
651    ///\e
652    Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
653
654    ///\e
655
656    ///\return
657    ///- \ref INF or -\ref INF means either infeasibility or unboundedness
658    /// of the primal problem, depending on whether we minimize or maximize.
659    ///- \ref NAN if no primal solution is found.
660    ///- The (finite) objective value if an optimal solution is found.
661    Value primalValue() { return _getPrimalValue()+obj_const_comp;}
662    ///@}
663   
664  }; 
665
666  ///\e
667 
668  ///\relates LpSolverBase::Expr
669  ///
670  inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
671                                      const LpSolverBase::Expr &b)
672  {
673    LpSolverBase::Expr tmp(a);
674    tmp+=b; ///\todo Don't STL have some special 'merge' algorithm?
675    return tmp;
676  }
677  ///\e
678 
679  ///\relates LpSolverBase::Expr
680  ///
681  inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
682                                      const LpSolverBase::Expr &b)
683  {
684    LpSolverBase::Expr tmp(a);
685    tmp-=b; ///\todo Don't STL have some special 'merge' algorithm?
686    return tmp;
687  }
688  ///\e
689 
690  ///\relates LpSolverBase::Expr
691  ///
692  inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
693                                      const LpSolverBase::Value &b)
694  {
695    LpSolverBase::Expr tmp(a);
696    tmp*=b; ///\todo Don't STL have some special 'merge' algorithm?
697    return tmp;
698  }
699 
700  ///\e
701 
702  ///\relates LpSolverBase::Expr
703  ///
704  inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
705                                      const LpSolverBase::Expr &b)
706  {
707    LpSolverBase::Expr tmp(b);
708    tmp*=a; ///\todo Don't STL have some special 'merge' algorithm?
709    return tmp;
710  }
711  ///\e
712 
713  ///\relates LpSolverBase::Expr
714  ///
715  inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
716                                      const LpSolverBase::Value &b)
717  {
718    LpSolverBase::Expr tmp(a);
719    tmp/=b; ///\todo Don't STL have some special 'merge' algorithm?
720    return tmp;
721  }
722 
723  ///\e
724 
725  ///\relates LpSolverBase::Constr
726  ///
727  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
728                                         const LpSolverBase::Expr &f)
729  {
730    return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
731  }
732
733  ///\e
734 
735  ///\relates LpSolverBase::Constr
736  ///
737  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
738                                         const LpSolverBase::Expr &f)
739  {
740    return LpSolverBase::Constr(e,f);
741  }
742
743  ///\e
744 
745  ///\relates LpSolverBase::Constr
746  ///
747  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
748                                         const LpSolverBase::Value &f)
749  {
750    return LpSolverBase::Constr(e,f);
751  }
752
753  ///\e
754 
755  ///\relates LpSolverBase::Constr
756  ///
757  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
758                                         const LpSolverBase::Expr &f)
759  {
760    return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
761  }
762
763
764  ///\e
765 
766  ///\relates LpSolverBase::Constr
767  ///
768  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
769                                         const LpSolverBase::Expr &f)
770  {
771    return LpSolverBase::Constr(f,e);
772  }
773
774
775  ///\e
776 
777  ///\relates LpSolverBase::Constr
778  ///
779  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
780                                         const LpSolverBase::Value &f)
781  {
782    return LpSolverBase::Constr(f,e);
783  }
784
785  ///\e
786 
787  ///\relates LpSolverBase::Constr
788  ///
789  inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
790                                         const LpSolverBase::Expr &f)
791  {
792    return LpSolverBase::Constr(0,e-f,0);
793  }
794
795  ///\e
796 
797  ///\relates LpSolverBase::Constr
798  ///
799  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
800                                         const LpSolverBase::Constr&c)
801  {
802    LpSolverBase::Constr tmp(c);
803    ///\todo Create an own exception type.
804    if(!isnan(tmp.lowerBound())) throw LogicError();
805    else tmp.lowerBound()=n;
806    return tmp;
807  }
808  ///\e
809 
810  ///\relates LpSolverBase::Constr
811  ///
812  inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
813                                         const LpSolverBase::Value &n)
814  {
815    LpSolverBase::Constr tmp(c);
816    ///\todo Create an own exception type.
817    if(!isnan(tmp.upperBound())) throw LogicError();
818    else tmp.upperBound()=n;
819    return tmp;
820  }
821
822  ///\e
823 
824  ///\relates LpSolverBase::Constr
825  ///
826  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
827                                         const LpSolverBase::Constr&c)
828  {
829    LpSolverBase::Constr tmp(c);
830    ///\todo Create an own exception type.
831    if(!isnan(tmp.upperBound())) throw LogicError();
832    else tmp.upperBound()=n;
833    return tmp;
834  }
835  ///\e
836 
837  ///\relates LpSolverBase::Constr
838  ///
839  inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
840                                         const LpSolverBase::Value &n)
841  {
842    LpSolverBase::Constr tmp(c);
843    ///\todo Create an own exception type.
844    if(!isnan(tmp.lowerBound())) throw LogicError();
845    else tmp.lowerBound()=n;
846    return tmp;
847  }
848
849
850} //namespace lemon
851
852#endif //LEMON_LP_BASE_H
Note: See TracBrowser for help on using the repository browser.