COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/athos/lp/lp_base.h @ 1279:7caed393608e

Last change on this file since 1279:7caed393608e was 1279:7caed393608e, checked in by Alpar Juttner, 20 years ago

LpSolverBase::Expr is documented

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