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