COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lp_base.h @ 1307:d4acebef7276

Last change on this file since 1307:d4acebef7276 was 1305:c3dc75d4af24, checked in by Akos Ladanyi, 19 years ago
  • moved lp_base.h, lp_base.cc, lp_glpk.h, lp_glpk.cc, lp_solver_skeleton.h and lp_solver_skeleton.cc to src/lemon
  • modified the includes
File size: 21.8 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    virtual int _addCol() = 0;
379    virtual int _addRow() = 0;
380    virtual void _setRowCoeffs(int i,
381                               int length,
382                               int  const * indices,
383                               Value  const * values ) = 0;
384    virtual void _setColCoeffs(int i,
385                               int length,
386                               int  const * indices,
387                               Value  const * values ) = 0;
388    virtual void _setColLowerBound(int i, Value value) = 0;
389    virtual void _setColUpperBound(int i, Value value) = 0;
390    virtual void _setRowLowerBound(int i, Value value) = 0;
391    virtual void _setRowUpperBound(int i, Value value) = 0;
392    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
393    virtual SolveExitStatus _solve() = 0;
394    virtual Value _getPrimal(int i) = 0;
395    virtual SolutionStatus _getPrimalType() = 0;
396
397
398    void clearObj() {}
399  public:
400
401
402    ///\e
403    virtual ~LpSolverBase() {}
404
405    ///\name Build up and modify of the LP
406
407    ///@{
408
409    ///Add a new empty column (i.e a new variable) to the LP
410    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
411
412    ///\brief Adds several new columns
413    ///(i.e a variables) at once
414    ///
415    ///This magic function takes a container as its argument
416    ///and fills its elements
417    ///with new columns (i.e. variables)
418    ///\param t can be
419    ///- a standard STL compatible iterable container with
420    ///\ref Col as its \c values_type
421    ///like
422    ///\code
423    ///std::vector<LpSolverBase::Col>
424    ///std::list<LpSolverBase::Col>
425    ///\endcode
426    ///- a standard STL compatible iterable container with
427    ///\ref Col as its \c mapped_type
428    ///like
429    ///\code
430    ///std::map<AnyType,LpSolverBase::Col>
431    ///\endcode
432    ///- an iterable lemon \ref concept::WriteMap "write map" like
433    ///\code
434    ///ListGraph::NodeMap<LpSolverBase::Col>
435    ///ListGraph::EdgeMap<LpSolverBase::Col>
436    ///\endcode
437    ///\return The number of the created column.
438    ///\bug Iterable nodemap hasn't been implemented yet.
439#ifdef DOXYGEN
440    template<class T>
441    int addColSet(T &t) { return 0;}
442#else
443    template<class T>
444    typename enable_if<typename T::value_type::LpSolverCol,int>::type
445    addColSet(T &t,dummy<0> = 0) {
446      int s=0;
447      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
448      return s;
449    }
450    template<class T>
451    typename enable_if<typename T::value_type::second_type::LpSolverCol,
452                       int>::type
453    addColSet(T &t,dummy<1> = 1) {
454      int s=0;
455      for(typename T::iterator i=t.begin();i!=t.end();++i) {
456        i->second=addCol();
457        s++;
458      }
459      return s;
460    }
461    template<class T>
462    typename enable_if<typename T::ValueSet::value_type::LpSolverCol,
463                       int>::type
464    addColSet(T &t,dummy<2> = 2) {
465      ///\bug <tt>return addColSet(t.valueSet());</tt> should also work.
466      int s=0;
467      for(typename T::ValueSet::iterator i=t.valueSet().begin();
468          i!=t.valueSet().end();
469          ++i)
470        {
471          *i=addCol();
472          s++;
473        }
474      return s;
475    }
476#endif
477
478    ///Add a new empty row (i.e a new constaint) to the LP
479
480    ///This function adds a new empty row (i.e a new constaint) to the LP.
481    ///\return The created row
482    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
483
484    ///Set a row (i.e a constaint) of the LP
485
486    ///\param r is the row to be modified
487    ///\param l is lower bound (-\ref INF means no bound)
488    ///\param e is a linear expression (see \ref Expr)
489    ///\param u is the upper bound (\ref INF means no bound)
490    ///\bug This is a temportary function. The interface will change to
491    ///a better one.
492    void setRow(Row r, Value l,const Expr &e, Value u) {
493      std::vector<int> indices;
494      std::vector<Value> values;
495      indices.push_back(0);
496      values.push_back(0);
497      for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
498        if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
499          indices.push_back(cols.floatingId((*i).first.id));
500          values.push_back((*i).second);
501        }
502      _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
503                    &indices[0],&values[0]);
504      _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
505      _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
506    }
507
508    ///Set a row (i.e a constaint) of the LP
509
510    ///\param r is the row to be modified
511    ///\param c is a linear expression (see \ref Constr)
512    void setRow(Row r, const Constr &c) {
513      setRow(r,
514             c.lowerBounded()?c.lowerBound():-INF,
515             c.expr(),
516             c.upperBounded()?c.upperBound():INF);
517    }
518
519    ///Add a new row (i.e a new constaint) to the LP
520
521    ///\param l is the lower bound (-\ref INF means no bound)
522    ///\param e is a linear expression (see \ref Expr)
523    ///\param u is the upper bound (\ref INF means no bound)
524    ///\return The created row.
525    ///\bug This is a temportary function. The interface will change to
526    ///a better one.
527    Row addRow(Value l,const Expr &e, Value u) {
528      Row r=addRow();
529      setRow(r,l,e,u);
530      return r;
531    }
532
533    ///Add a new row (i.e a new constaint) to the LP
534
535    ///\param c is a linear expression (see \ref Constr)
536    ///\return The created row.
537    Row addRow(const Constr &c) {
538      Row r=addRow();
539      setRow(r,c);
540      return r;
541    }
542
543    /// Set the lower bound of a column (i.e a variable)
544
545    /// The upper bound of a variable (column) has to be given by an
546    /// extended number of type Value, i.e. a finite number of type
547    /// Value or -\ref INF.
548    void colLowerBound(Col c, Value value) {
549      _setColLowerBound(cols.floatingId(c.id),value);
550    }
551    /// Set the upper bound of a column (i.e a variable)
552
553    /// The upper bound of a variable (column) has to be given by an
554    /// extended number of type Value, i.e. a finite number of type
555    /// Value or \ref INF.
556    void colUpperBound(Col c, Value value) {
557      _setColUpperBound(cols.floatingId(c.id),value);
558    };
559    /// Set the lower and the upper bounds of a column (i.e a variable)
560
561    /// The lower and the upper bounds of
562    /// a variable (column) have to be given by an
563    /// extended number of type Value, i.e. a finite number of type
564    /// Value, -\ref INF or \ref INF.
565    void colBounds(Col c, Value lower, Value upper) {
566      _setColLowerBound(cols.floatingId(c.id),lower);
567      _setColUpperBound(cols.floatingId(c.id),upper);
568    }
569   
570    /// Set the lower bound of a row (i.e a constraint)
571
572    /// The lower bound of a linear expression (row) has to be given by an
573    /// extended number of type Value, i.e. a finite number of type
574    /// Value or -\ref INF.
575    void rowLowerBound(Row r, Value value) {
576      _setRowLowerBound(rows.floatingId(r.id),value);
577    };
578    /// Set the upper bound of a row (i.e a constraint)
579
580    /// The upper bound of a linear expression (row) has to be given by an
581    /// extended number of type Value, i.e. a finite number of type
582    /// Value or \ref INF.
583    void rowUpperBound(Row r, Value value) {
584      _setRowUpperBound(rows.floatingId(r.id),value);
585    };
586    /// Set the lower and the upper bounds of a row (i.e a variable)
587
588    /// The lower and the upper bounds of
589    /// a constraint (row) have to be given by an
590    /// extended number of type Value, i.e. a finite number of type
591    /// Value, -\ref INF or \ref INF.
592    void rowBounds(Row c, Value lower, Value upper) {
593      _setRowLowerBound(rows.floatingId(c.id),lower);
594      _setRowUpperBound(rows.floatingId(c.id),upper);
595    }
596   
597    ///Set an element of the objective function
598    void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
599    ///Set the objective function
600   
601    ///\param e is a linear expression of type \ref Expr.
602    ///\todo What to do with the constant component?
603    void setObj(Expr e) {
604      clearObj();
605      for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
606        objCoeff((*i).first,(*i).second);
607    }
608
609    ///@}
610
611
612    ///\name Solve the LP
613
614    ///@{
615
616    ///\e
617    SolveExitStatus solve() { return _solve(); }
618   
619    ///@}
620   
621    ///\name Obtain the solution
622
623    ///@{
624
625    ///\e
626    SolutionStatus primalType() {
627      return _getPrimalType();
628    }
629
630    ///\e
631    Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
632
633    ///@}
634   
635  }; 
636
637  ///\e
638 
639  ///\relates LpSolverBase::Expr
640  ///
641  inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
642                                      const LpSolverBase::Expr &b)
643  {
644    LpSolverBase::Expr tmp(a);
645    tmp+=b; ///\todo Don't STL have some special 'merge' algorithm?
646    return tmp;
647  }
648  ///\e
649 
650  ///\relates LpSolverBase::Expr
651  ///
652  inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
653                                      const LpSolverBase::Expr &b)
654  {
655    LpSolverBase::Expr tmp(a);
656    tmp-=b; ///\todo Don't STL have some special 'merge' algorithm?
657    return tmp;
658  }
659  ///\e
660 
661  ///\relates LpSolverBase::Expr
662  ///
663  inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
664                                      const LpSolverBase::Value &b)
665  {
666    LpSolverBase::Expr tmp(a);
667    tmp*=b; ///\todo Don't STL have some special 'merge' algorithm?
668    return tmp;
669  }
670 
671  ///\e
672 
673  ///\relates LpSolverBase::Expr
674  ///
675  inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
676                                      const LpSolverBase::Expr &b)
677  {
678    LpSolverBase::Expr tmp(b);
679    tmp*=a; ///\todo Don't STL have some special 'merge' algorithm?
680    return tmp;
681  }
682  ///\e
683 
684  ///\relates LpSolverBase::Expr
685  ///
686  inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
687                                      const LpSolverBase::Value &b)
688  {
689    LpSolverBase::Expr tmp(a);
690    tmp/=b; ///\todo Don't STL have some special 'merge' algorithm?
691    return tmp;
692  }
693 
694  ///\e
695 
696  ///\relates LpSolverBase::Constr
697  ///
698  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
699                                         const LpSolverBase::Expr &f)
700  {
701    return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
702  }
703
704  ///\e
705 
706  ///\relates LpSolverBase::Constr
707  ///
708  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
709                                         const LpSolverBase::Expr &f)
710  {
711    return LpSolverBase::Constr(e,f);
712  }
713
714  ///\e
715 
716  ///\relates LpSolverBase::Constr
717  ///
718  inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
719                                         const LpSolverBase::Value &f)
720  {
721    return LpSolverBase::Constr(e,f);
722  }
723
724  ///\e
725 
726  ///\relates LpSolverBase::Constr
727  ///
728  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
729                                         const LpSolverBase::Expr &f)
730  {
731    return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
732  }
733
734
735  ///\e
736 
737  ///\relates LpSolverBase::Constr
738  ///
739  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
740                                         const LpSolverBase::Expr &f)
741  {
742    return LpSolverBase::Constr(f,e);
743  }
744
745
746  ///\e
747 
748  ///\relates LpSolverBase::Constr
749  ///
750  inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
751                                         const LpSolverBase::Value &f)
752  {
753    return LpSolverBase::Constr(f,e);
754  }
755
756  ///\e
757 
758  ///\relates LpSolverBase::Constr
759  ///
760  inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
761                                         const LpSolverBase::Expr &f)
762  {
763    return LpSolverBase::Constr(0,e-f,0);
764  }
765
766  ///\e
767 
768  ///\relates LpSolverBase::Constr
769  ///
770  inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
771                                         const LpSolverBase::Constr&c)
772  {
773    LpSolverBase::Constr tmp(c);
774    ///\todo Create an own exception type.
775    if(!isnan(tmp.lowerBound())) throw LogicError();
776    else tmp.lowerBound()=n;
777    return tmp;
778  }
779  ///\e
780 
781  ///\relates LpSolverBase::Constr
782  ///
783  inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
784                                         const LpSolverBase::Value &n)
785  {
786    LpSolverBase::Constr tmp(c);
787    ///\todo Create an own exception type.
788    if(!isnan(tmp.upperBound())) throw LogicError();
789    else tmp.upperBound()=n;
790    return tmp;
791  }
792
793  ///\e
794 
795  ///\relates LpSolverBase::Constr
796  ///
797  inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
798                                         const LpSolverBase::Constr&c)
799  {
800    LpSolverBase::Constr tmp(c);
801    ///\todo Create an own exception type.
802    if(!isnan(tmp.upperBound())) throw LogicError();
803    else tmp.upperBound()=n;
804    return tmp;
805  }
806  ///\e
807 
808  ///\relates LpSolverBase::Constr
809  ///
810  inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
811                                         const LpSolverBase::Value &n)
812  {
813    LpSolverBase::Constr tmp(c);
814    ///\todo Create an own exception type.
815    if(!isnan(tmp.lowerBound())) throw LogicError();
816    else tmp.lowerBound()=n;
817    return tmp;
818  }
819
820
821} //namespace lemon
822
823#endif //LEMON_LP_BASE_H
Note: See TracBrowser for help on using the repository browser.