COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/athos/lp/lp_base.h @ 1291:16cde3e1aa9f

Last change on this file since 1291:16cde3e1aa9f was 1291:16cde3e1aa9f, checked in by athos, 15 years ago

Conceptions and bug fixes.

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