src/lemon/lp_base.h
author ladanyi
Thu, 14 Apr 2005 21:23:25 +0000
changeset 1355 57936f15055b
parent 1323 3aaadfb7de3d
child 1359 1581f961cfaa
permissions -rw-r--r--
- Use messages similar to stock autoconf macros'.
     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 ///\ingroup gen_opt_group
    34 namespace lemon {
    35   
    36   ///Internal data structure to convert floating id's to fix one's
    37     
    38   ///\todo This might be implemented to be also usable in other places.
    39   class _FixId 
    40   {
    41     std::vector<int> index;
    42     std::vector<int> cross;
    43     int first_free;
    44   public:
    45     _FixId() : first_free(-1) {};
    46     ///Convert a floating id to a fix one
    47 
    48     ///\param n is a floating id
    49     ///\return the corresponding fix id
    50     int fixId(int n) {return cross[n];}
    51     ///Convert a fix id to a floating one
    52 
    53     ///\param n is a fix id
    54     ///\return the corresponding floating id
    55     int floatingId(int n) { return index[n];}
    56     ///Add a new floating id.
    57 
    58     ///\param n is a floating id
    59     ///\return the fix id of the new value
    60     ///\todo Multiple additions should also be handled.
    61     int insert(int n)
    62     {
    63       if(n>=int(cross.size())) {
    64 	cross.resize(n+1);
    65 	if(first_free==-1) {
    66 	  cross[n]=index.size();
    67 	  index.push_back(n);
    68 	}
    69 	else {
    70 	  cross[n]=first_free;
    71 	  int next=index[first_free];
    72 	  index[first_free]=n;
    73 	  first_free=next;
    74 	}
    75 	return cross[n];
    76       }
    77       ///\todo Create an own exception type.
    78       else throw LogicError(); //floatingId-s must form a continuous range;
    79     }
    80     ///Remove a fix id.
    81 
    82     ///\param n is a fix id
    83     ///
    84     void erase(int n) 
    85     {
    86       int fl=index[n];
    87       index[n]=first_free;
    88       first_free=n;
    89       for(int i=fl+1;i<int(cross.size());++i) {
    90 	cross[i-1]=cross[i];
    91 	index[cross[i]]--;
    92       }
    93       cross.pop_back();
    94     }
    95     ///An upper bound on the largest fix id.
    96 
    97     ///\todo Do we need this?
    98     ///
    99     std::size_t maxFixId() { return cross.size()-1; }
   100   
   101   };
   102     
   103   ///Common base class for LP solvers
   104   
   105   ///\todo Much more docs
   106   ///\ingroup gen_opt_group
   107   class LpSolverBase {
   108 
   109   public:
   110 
   111     ///\e
   112     enum SolveExitStatus {
   113       ///\e
   114       SOLVED = 0,
   115       ///\e
   116       UNSOLVED = 1
   117     };
   118       
   119     ///\e
   120     enum SolutionStatus {
   121       ///Feasible solution has'n been found (but may exist).
   122 
   123       ///\todo NOTFOUND might be a better name.
   124       ///
   125       UNDEFINED = 0,
   126       ///The problem has no feasible solution
   127       INFEASIBLE = 1,
   128       ///Feasible solution found
   129       FEASIBLE = 2,
   130       ///Optimal solution exists and found
   131       OPTIMAL = 3,
   132       ///The cost function is unbounded
   133 
   134       ///\todo Give a feasible solution and an infinite ray (and the
   135       ///corresponding bases)
   136       INFINITE = 4
   137     };
   138       
   139     ///The floating point type used by the solver
   140     typedef double Value;
   141     ///The infinity constant
   142     static const Value INF;
   143     ///The not a number constant
   144     static const Value NaN;
   145     
   146     ///Refer to a column of the LP.
   147 
   148     ///This type is used to refer to a column of the LP.
   149     ///
   150     ///Its value remains valid and correct even after the addition or erase of
   151     ///other columns.
   152     ///
   153     ///\todo Document what can one do with a Col (INVALID, comparing,
   154     ///it is similar to Node/Edge)
   155     class Col {
   156     protected:
   157       int id;
   158       friend class LpSolverBase;
   159     public:
   160       typedef Value ExprValue;
   161       typedef True LpSolverCol;
   162       Col() {}
   163       Col(const Invalid&) : id(-1) {}
   164       bool operator<(Col c) const  {return id<c.id;}
   165       bool operator==(Col c) const  {return id==c.id;}
   166       bool operator!=(Col c) const  {return id==c.id;}
   167     };
   168 
   169     ///Refer to a row of the LP.
   170 
   171     ///This type is used to refer to a row of the LP.
   172     ///
   173     ///Its value remains valid and correct even after the addition or erase of
   174     ///other rows.
   175     ///
   176     ///\todo Document what can one do with a Row (INVALID, comparing,
   177     ///it is similar to Node/Edge)
   178     class Row {
   179     protected:
   180       int id;
   181       friend class LpSolverBase;
   182     public:
   183       typedef Value ExprValue;
   184       typedef True LpSolverRow;
   185       Row() {}
   186       Row(const Invalid&) : id(-1) {}
   187       typedef True LpSolverRow;
   188       bool operator<(Row c) const  {return id<c.id;}
   189       bool operator==(Row c) const  {return id==c.id;}
   190       bool operator!=(Row c) const  {return id==c.id;} 
   191    };
   192     
   193     ///Linear expression of variables and a constant component
   194     
   195     ///This data structure strores a linear expression of the variables
   196     ///(\ref Col "Col"s) and also has a constant component.
   197     ///
   198     ///There are several ways to access and modify the contents of this
   199     ///container.
   200     ///- Its it fully compatible with \c std::map<Col,double>, so for expamle
   201     ///if \c e is an Expr and \c v and \c w are of type \ref Col then you can
   202     ///read and modify the coefficients like
   203     ///these.
   204     ///\code
   205     ///e[v]=5;
   206     ///e[v]+=12;
   207     ///e.erase(v);
   208     ///\endcode
   209     ///or you can also iterate through its elements.
   210     ///\code
   211     ///double s=0;
   212     ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i)
   213     ///  s+=i->second;
   214     ///\endcode
   215     ///(This code computes the sum of all coefficients).
   216     ///- Numbers (<tt>double</tt>'s)
   217     ///and variables (\ref Col "Col"s) directly convert to an
   218     ///\ref Expr and the usual linear operations are defined so  
   219     ///\code
   220     ///v+w
   221     ///2*v-3.12*(v-w/2)+2
   222     ///v*2.1+(3*v+(v*12+w+6)*3)/2
   223     ///\endcode
   224     ///are valid \ref Expr "Expr"essions.
   225     ///The usual assignment operations are also defined.
   226     ///\code
   227     ///e=v+w;
   228     ///e+=2*v-3.12*(v-w/2)+2;
   229     ///e*=3.4;
   230     ///e/=5;
   231     ///\endcode
   232     ///- The constant member can be set and read by \ref constComp()
   233     ///\code
   234     ///e.constComp()=12;
   235     ///double c=e.constComp();
   236     ///\endcode
   237     ///
   238     ///\note \ref clear() not only sets all coefficients to 0 but also
   239     ///clears the constant components.
   240     ///
   241     ///\sa Constr
   242     ///
   243     class Expr : public std::map<Col,Value>
   244     {
   245     public:
   246       typedef LpSolverBase::Col Key; 
   247       typedef LpSolverBase::Value Value;
   248       
   249     protected:
   250       typedef std::map<Col,Value> Base;
   251       
   252       Value const_comp;
   253   public:
   254       typedef True IsLinExpression;
   255       ///\e
   256       Expr() : Base(), const_comp(0) { }
   257       ///\e
   258       Expr(const Key &v) : const_comp(0) {
   259 	Base::insert(std::make_pair(v, 1));
   260       }
   261       ///\e
   262       Expr(const Value &v) : const_comp(v) {}
   263       ///\e
   264       void set(const Key &v,const Value &c) {
   265 	Base::insert(std::make_pair(v, c));
   266       }
   267       ///\e
   268       Value &constComp() { return const_comp; }
   269       ///\e
   270       const Value &constComp() const { return const_comp; }
   271       
   272       ///Removes the components with zero coefficient.
   273       void simplify() {
   274 	for (Base::iterator i=Base::begin(); i!=Base::end();) {
   275 	  Base::iterator j=i;
   276 	  ++j;
   277 	  if ((*i).second==0) Base::erase(i);
   278 	  j=i;
   279 	}
   280       }
   281 
   282       ///Sets all coefficients and the constant component to 0.
   283       void clear() {
   284 	Base::clear();
   285 	const_comp=0;
   286       }
   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 	///\todo it might be speeded up using "hints"
   293 	const_comp+=e.const_comp;
   294 	return *this;
   295       }
   296       ///\e
   297       Expr &operator-=(const Expr &e) {
   298 	for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
   299 	  (*this)[j->first]-=j->second;
   300 	const_comp-=e.const_comp;
   301 	return *this;
   302       }
   303       ///\e
   304       Expr &operator*=(const Value &c) {
   305 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   306 	  j->second*=c;
   307 	const_comp*=c;
   308 	return *this;
   309       }
   310       ///\e
   311       Expr &operator/=(const Value &c) {
   312 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   313 	  j->second/=c;
   314 	const_comp/=c;
   315 	return *this;
   316       }
   317     };
   318     
   319     ///Linear constraint
   320 
   321     ///\todo document please
   322     ///
   323     class Constr
   324     {
   325     public:
   326       typedef LpSolverBase::Expr Expr;
   327       typedef Expr::Key Key;
   328       typedef Expr::Value Value;
   329       
   330       static const Value INF;
   331       static const Value NaN;
   332       //     static const Value INF=0;
   333       //     static const Value NaN=1;
   334       
   335     protected:
   336       Expr _expr;
   337       Value _lb,_ub;
   338     public:
   339       ///\e
   340       Constr() : _expr(), _lb(NaN), _ub(NaN) {}
   341       ///\e
   342       Constr(Value lb,const Expr &e,Value ub) :
   343 	_expr(e), _lb(lb), _ub(ub) {}
   344       ///\e
   345       Constr(const Expr &e,Value ub) : 
   346 	_expr(e), _lb(NaN), _ub(ub) {}
   347       ///\e
   348       Constr(Value lb,const Expr &e) :
   349 	_expr(e), _lb(lb), _ub(NaN) {}
   350       ///\e
   351       Constr(const Expr &e) : 
   352 	_expr(e), _lb(NaN), _ub(NaN) {}
   353       ///\e
   354       void clear() 
   355       {
   356 	_expr.clear();
   357 	_lb=_ub=NaN;
   358       }
   359       ///\e
   360       Expr &expr() { return _expr; }
   361       ///\e
   362       const Expr &expr() const { return _expr; }
   363       ///\e
   364       Value &lowerBound() { return _lb; }
   365       ///\e
   366       const Value &lowerBound() const { return _lb; }
   367       ///\e
   368       Value &upperBound() { return _ub; }
   369       ///\e
   370       const Value &upperBound() const { return _ub; }
   371       ///\e
   372       bool lowerBounded() const { 
   373 	using namespace std;
   374 	return isfinite(_lb);
   375       }
   376       ///\e
   377       bool upperBounded() const {
   378 	using namespace std;
   379 	return isfinite(_ub);
   380       }
   381     };
   382     
   383 
   384   protected:
   385     _FixId rows;
   386     _FixId cols;
   387 
   388     //Abstract virtual functions
   389     virtual int _addCol() = 0;
   390     virtual int _addRow() = 0;
   391     virtual void _setRowCoeffs(int i, 
   392 			       int length,
   393                                int  const * indices, 
   394                                Value  const * values ) = 0;
   395     virtual void _setColCoeffs(int i, 
   396 			       int length,
   397                                int  const * indices, 
   398                                Value  const * values ) = 0;
   399     virtual void _setColLowerBound(int i, Value value) = 0;
   400     virtual void _setColUpperBound(int i, Value value) = 0;
   401     virtual void _setRowLowerBound(int i, Value value) = 0;
   402     virtual void _setRowUpperBound(int i, Value value) = 0;
   403     virtual void _setObjCoeff(int i, Value obj_coef) = 0;
   404     virtual SolveExitStatus _solve() = 0;
   405     virtual Value _getPrimal(int i) = 0;
   406     virtual Value _getPrimalValue() = 0;
   407     virtual SolutionStatus _getPrimalStatus() = 0;
   408     virtual void _setMax() = 0;
   409     virtual void _setMin() = 0;
   410     
   411     //Own protected stuff
   412     
   413     //Constant component of the objective function
   414     Value obj_const_comp;
   415     
   416     ///\e
   417     
   418     ///\bug Unimplemented
   419     void clearObj() {}
   420     
   421   public:
   422 
   423     ///\e
   424     LpSolverBase() : obj_const_comp(0) {}
   425 
   426     ///\e
   427     virtual ~LpSolverBase() {}
   428 
   429     ///\name Build up and modify of the LP
   430 
   431     ///@{
   432 
   433     ///Add a new empty column (i.e a new variable) to the LP
   434     Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
   435 
   436     ///\brief Adds several new columns
   437     ///(i.e a variables) at once
   438     ///
   439     ///This magic function takes a container as its argument
   440     ///and fills its elements
   441     ///with new columns (i.e. variables)
   442     ///\param t can be
   443     ///- a standard STL compatible iterable container with
   444     ///\ref Col as its \c values_type
   445     ///like
   446     ///\code
   447     ///std::vector<LpSolverBase::Col>
   448     ///std::list<LpSolverBase::Col>
   449     ///\endcode
   450     ///- a standard STL compatible iterable container with
   451     ///\ref Col as its \c mapped_type
   452     ///like
   453     ///\code
   454     ///std::map<AnyStatus,LpSolverBase::Col>
   455     ///\endcode
   456     ///- an iterable lemon \ref concept::WriteMap "write map" like 
   457     ///\code
   458     ///ListGraph::NodeMap<LpSolverBase::Col>
   459     ///ListGraph::EdgeMap<LpSolverBase::Col>
   460     ///\endcode
   461     ///\return The number of the created column.
   462     ///\bug Iterable nodemap hasn't been implemented yet.
   463 #ifdef DOXYGEN
   464     template<class T>
   465     int addColSet(T &t) { return 0;} 
   466 #else
   467     template<class T>
   468     typename enable_if<typename T::value_type::LpSolverCol,int>::type
   469     addColSet(T &t,dummy<0> = 0) {
   470       int s=0;
   471       for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
   472       return s;
   473     }
   474     template<class T>
   475     typename enable_if<typename T::value_type::second_type::LpSolverCol,
   476 		       int>::type
   477     addColSet(T &t,dummy<1> = 1) { 
   478       int s=0;
   479       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   480 	i->second=addCol();
   481 	s++;
   482       }
   483       return s;
   484     }
   485     template<class T>
   486     typename enable_if<typename T::ValueSet::value_type::LpSolverCol,
   487 		       int>::type
   488     addColSet(T &t,dummy<2> = 2) { 
   489       ///\bug <tt>return addColSet(t.valueSet());</tt> should also work.
   490       int s=0;
   491       for(typename T::ValueSet::iterator i=t.valueSet().begin();
   492 	  i!=t.valueSet().end();
   493 	  ++i)
   494 	{
   495 	  *i=addCol();
   496 	  s++;
   497 	}
   498       return s;
   499     }
   500 #endif
   501 
   502     ///Add a new empty row (i.e a new constaint) to the LP
   503 
   504     ///This function adds a new empty row (i.e a new constaint) to the LP.
   505     ///\return The created row
   506     Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
   507 
   508     ///Set a row (i.e a constaint) of the LP
   509 
   510     ///\param r is the row to be modified
   511     ///\param l is lower bound (-\ref INF means no bound)
   512     ///\param e is a linear expression (see \ref Expr)
   513     ///\param u is the upper bound (\ref INF means no bound)
   514     ///\bug This is a temportary function. The interface will change to
   515     ///a better one.
   516     ///\todo Option to control whether a constraint with a single variable is
   517     ///added or not.
   518     void setRow(Row r, Value l,const Expr &e, Value u) {
   519       std::vector<int> indices;
   520       std::vector<Value> values;
   521       indices.push_back(0);
   522       values.push_back(0);
   523       for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
   524 	if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
   525 	  indices.push_back(cols.floatingId((*i).first.id));
   526 	  values.push_back((*i).second);
   527 	}
   528       _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
   529 		    &indices[0],&values[0]);
   530       _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
   531       _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
   532     }
   533 
   534     ///Set a row (i.e a constaint) of the LP
   535 
   536     ///\param r is the row to be modified
   537     ///\param c is a linear expression (see \ref Constr)
   538     void setRow(Row r, const Constr &c) {
   539       setRow(r,
   540 	     c.lowerBounded()?c.lowerBound():-INF,
   541 	     c.expr(),
   542 	     c.upperBounded()?c.upperBound():INF);
   543     }
   544 
   545     ///Add a new row (i.e a new constaint) to the LP
   546 
   547     ///\param l is the lower bound (-\ref INF means no bound)
   548     ///\param e is a linear expression (see \ref Expr)
   549     ///\param u is the upper bound (\ref INF means no bound)
   550     ///\return The created row.
   551     ///\bug This is a temportary function. The interface will change to
   552     ///a better one.
   553     Row addRow(Value l,const Expr &e, Value u) {
   554       Row r=addRow();
   555       setRow(r,l,e,u);
   556       return r;
   557     }
   558 
   559     ///Add a new row (i.e a new constaint) to the LP
   560 
   561     ///\param c is a linear expression (see \ref Constr)
   562     ///\return The created row.
   563     Row addRow(const Constr &c) {
   564       Row r=addRow();
   565       setRow(r,c);
   566       return r;
   567     }
   568 
   569     /// Set the lower bound of a column (i.e a variable)
   570 
   571     /// The upper bound of a variable (column) has to be given by an 
   572     /// extended number of type Value, i.e. a finite number of type 
   573     /// Value or -\ref INF.
   574     void colLowerBound(Col c, Value value) {
   575       _setColLowerBound(cols.floatingId(c.id),value);
   576     }
   577     /// Set the upper bound of a column (i.e a variable)
   578 
   579     /// The upper bound of a variable (column) has to be given by an 
   580     /// extended number of type Value, i.e. a finite number of type 
   581     /// Value or \ref INF.
   582     void colUpperBound(Col c, Value value) {
   583       _setColUpperBound(cols.floatingId(c.id),value);
   584     };
   585     /// Set the lower and the upper bounds of a column (i.e a variable)
   586 
   587     /// The lower and the upper bounds of
   588     /// a variable (column) have to be given by an 
   589     /// extended number of type Value, i.e. a finite number of type 
   590     /// Value, -\ref INF or \ref INF.
   591     void colBounds(Col c, Value lower, Value upper) {
   592       _setColLowerBound(cols.floatingId(c.id),lower);
   593       _setColUpperBound(cols.floatingId(c.id),upper);
   594     }
   595     
   596     /// Set the lower bound of a row (i.e a constraint)
   597 
   598     /// The lower bound of a linear expression (row) has to be given by an 
   599     /// extended number of type Value, i.e. a finite number of type 
   600     /// Value or -\ref INF.
   601     void rowLowerBound(Row r, Value value) {
   602       _setRowLowerBound(rows.floatingId(r.id),value);
   603     };
   604     /// Set the upper bound of a row (i.e a constraint)
   605 
   606     /// The upper bound of a linear expression (row) has to be given by an 
   607     /// extended number of type Value, i.e. a finite number of type 
   608     /// Value or \ref INF.
   609     void rowUpperBound(Row r, Value value) {
   610       _setRowUpperBound(rows.floatingId(r.id),value);
   611     };
   612     /// Set the lower and the upper bounds of a row (i.e a variable)
   613 
   614     /// The lower and the upper bounds of
   615     /// a constraint (row) have to be given by an 
   616     /// extended number of type Value, i.e. a finite number of type 
   617     /// Value, -\ref INF or \ref INF.
   618     void rowBounds(Row c, Value lower, Value upper) {
   619       _setRowLowerBound(rows.floatingId(c.id),lower);
   620       _setRowUpperBound(rows.floatingId(c.id),upper);
   621     }
   622     
   623     ///Set an element of the objective function
   624     void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
   625     ///Set the objective function
   626     
   627     ///\param e is a linear expression of type \ref Expr.
   628     ///\bug The previous objective function is not cleared!
   629     void setObj(Expr e) {
   630       clearObj();
   631       for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
   632 	objCoeff((*i).first,(*i).second);
   633       obj_const_comp=e.constComp();
   634     }
   635 
   636     ///Maximize
   637     void max() { _setMax(); }
   638     ///Minimize
   639     void min() { _setMin(); }
   640 
   641     
   642     ///@}
   643 
   644 
   645     ///\name Solve the LP
   646 
   647     ///@{
   648 
   649     ///\e
   650     SolveExitStatus solve() { return _solve(); }
   651     
   652     ///@}
   653     
   654     ///\name Obtain the solution
   655 
   656     ///@{
   657 
   658     ///\e
   659     SolutionStatus primalStatus() {
   660       return _getPrimalStatus();
   661     }
   662 
   663     ///\e
   664     Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
   665 
   666     ///\e
   667 
   668     ///\return
   669     ///- \ref INF or -\ref INF means either infeasibility or unboundedness
   670     /// of the primal problem, depending on whether we minimize or maximize.
   671     ///- \ref NAN if no primal solution is found.
   672     ///- The (finite) objective value if an optimal solution is found.
   673     Value primalValue() { return _getPrimalValue()+obj_const_comp;}
   674     ///@}
   675     
   676   };  
   677 
   678   ///\e
   679   
   680   ///\relates LpSolverBase::Expr
   681   ///
   682   inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
   683 				      const LpSolverBase::Expr &b) 
   684   {
   685     LpSolverBase::Expr tmp(a);
   686     tmp+=b; ///\todo Don't STL have some special 'merge' algorithm?
   687     return tmp;
   688   }
   689   ///\e
   690   
   691   ///\relates LpSolverBase::Expr
   692   ///
   693   inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
   694 				      const LpSolverBase::Expr &b) 
   695   {
   696     LpSolverBase::Expr tmp(a);
   697     tmp-=b; ///\todo Don't STL have some special 'merge' algorithm?
   698     return tmp;
   699   }
   700   ///\e
   701   
   702   ///\relates LpSolverBase::Expr
   703   ///
   704   inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
   705 				      const LpSolverBase::Value &b) 
   706   {
   707     LpSolverBase::Expr tmp(a);
   708     tmp*=b; ///\todo Don't STL have some special 'merge' algorithm?
   709     return tmp;
   710   }
   711   
   712   ///\e
   713   
   714   ///\relates LpSolverBase::Expr
   715   ///
   716   inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
   717 				      const LpSolverBase::Expr &b) 
   718   {
   719     LpSolverBase::Expr tmp(b);
   720     tmp*=a; ///\todo Don't STL have some special 'merge' algorithm?
   721     return tmp;
   722   }
   723   ///\e
   724   
   725   ///\relates LpSolverBase::Expr
   726   ///
   727   inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
   728 				      const LpSolverBase::Value &b) 
   729   {
   730     LpSolverBase::Expr tmp(a);
   731     tmp/=b; ///\todo Don't STL have some special 'merge' algorithm?
   732     return tmp;
   733   }
   734   
   735   ///\e
   736   
   737   ///\relates LpSolverBase::Constr
   738   ///
   739   inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
   740 					 const LpSolverBase::Expr &f) 
   741   {
   742     return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
   743   }
   744 
   745   ///\e
   746   
   747   ///\relates LpSolverBase::Constr
   748   ///
   749   inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
   750 					 const LpSolverBase::Expr &f) 
   751   {
   752     return LpSolverBase::Constr(e,f);
   753   }
   754 
   755   ///\e
   756   
   757   ///\relates LpSolverBase::Constr
   758   ///
   759   inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
   760 					 const LpSolverBase::Value &f) 
   761   {
   762     return LpSolverBase::Constr(e,f);
   763   }
   764 
   765   ///\e
   766   
   767   ///\relates LpSolverBase::Constr
   768   ///
   769   inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
   770 					 const LpSolverBase::Expr &f) 
   771   {
   772     return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
   773   }
   774 
   775 
   776   ///\e
   777   
   778   ///\relates LpSolverBase::Constr
   779   ///
   780   inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
   781 					 const LpSolverBase::Expr &f) 
   782   {
   783     return LpSolverBase::Constr(f,e);
   784   }
   785 
   786 
   787   ///\e
   788   
   789   ///\relates LpSolverBase::Constr
   790   ///
   791   inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
   792 					 const LpSolverBase::Value &f) 
   793   {
   794     return LpSolverBase::Constr(f,e);
   795   }
   796 
   797   ///\e
   798   
   799   ///\relates LpSolverBase::Constr
   800   ///
   801   inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
   802 					 const LpSolverBase::Expr &f) 
   803   {
   804     return LpSolverBase::Constr(0,e-f,0);
   805   }
   806 
   807   ///\e
   808   
   809   ///\relates LpSolverBase::Constr
   810   ///
   811   inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
   812 					 const LpSolverBase::Constr&c) 
   813   {
   814     LpSolverBase::Constr tmp(c);
   815     ///\todo Create an own exception type.
   816     if(!isnan(tmp.lowerBound())) throw LogicError();
   817     else tmp.lowerBound()=n;
   818     return tmp;
   819   }
   820   ///\e
   821   
   822   ///\relates LpSolverBase::Constr
   823   ///
   824   inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
   825 					 const LpSolverBase::Value &n)
   826   {
   827     LpSolverBase::Constr tmp(c);
   828     ///\todo Create an own exception type.
   829     if(!isnan(tmp.upperBound())) throw LogicError();
   830     else tmp.upperBound()=n;
   831     return tmp;
   832   }
   833 
   834   ///\e
   835   
   836   ///\relates LpSolverBase::Constr
   837   ///
   838   inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
   839 					 const LpSolverBase::Constr&c) 
   840   {
   841     LpSolverBase::Constr tmp(c);
   842     ///\todo Create an own exception type.
   843     if(!isnan(tmp.upperBound())) throw LogicError();
   844     else tmp.upperBound()=n;
   845     return tmp;
   846   }
   847   ///\e
   848   
   849   ///\relates LpSolverBase::Constr
   850   ///
   851   inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
   852 					 const LpSolverBase::Value &n)
   853   {
   854     LpSolverBase::Constr tmp(c);
   855     ///\todo Create an own exception type.
   856     if(!isnan(tmp.lowerBound())) throw LogicError();
   857     else tmp.lowerBound()=n;
   858     return tmp;
   859   }
   860 
   861 
   862 } //namespace lemon
   863 
   864 #endif //LEMON_LP_BASE_H