src/lemon/lp_base.h
author alpar
Wed, 06 Apr 2005 07:24:48 +0000
changeset 1309 b3ce42a4d7d2
parent 1303 9bcc455da4f5
child 1312 48f9299b390d
permissions -rw-r--r--
lp_test added
WARNING: Overall glpk dependency! (we should avoid)
     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 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