src/work/athos/lp/lp_base.h
author alpar
Thu, 31 Mar 2005 14:04:13 +0000
changeset 1284 b941d044f87b
parent 1275 16980bf77bd3
child 1291 16cde3e1aa9f
permissions -rw-r--r--
SmartGraph can also split() a node!
     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.
    33 namespace 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