lemon/lp_base.h
author alpar
Tue, 17 Oct 2006 11:05:23 +0000
changeset 2253 1645f6cc9667
parent 2185 e2bf51eab7f7
child 2260 4274224f8a7d
permissions -rw-r--r--
Remove superfluous #ifndef boundaries
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_LP_BASE_H
    20 #define LEMON_LP_BASE_H
    21 
    22 #include<vector>
    23 #include<map>
    24 #include<limits>
    25 #include<cmath>
    26 
    27 #include<lemon/bits/utility.h>
    28 #include<lemon/error.h>
    29 #include<lemon/bits/invalid.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   protected:
    42     std::vector<int> index;
    43     std::vector<int> cross;
    44     int first_free;
    45   public:
    46     _FixId() : first_free(-1) {};
    47     ///Convert a floating id to a fix one
    48 
    49     ///\param n is a floating id
    50     ///\return the corresponding fix id
    51     int fixId(int n) const {return cross[n];}
    52     ///Convert a fix id to a floating one
    53 
    54     ///\param n is a fix id
    55     ///\return the corresponding floating id
    56     int floatingId(int n) const { return index[n];}
    57     ///Add a new floating id.
    58 
    59     ///\param n is a floating id
    60     ///\return the fix id of the new value
    61     ///\todo Multiple additions should also be handled.
    62     int insert(int n)
    63     {
    64       if(n>=int(cross.size())) {
    65 	cross.resize(n+1);
    66 	if(first_free==-1) {
    67 	  cross[n]=index.size();
    68 	  index.push_back(n);
    69 	}
    70 	else {
    71 	  cross[n]=first_free;
    72 	  int next=index[first_free];
    73 	  index[first_free]=n;
    74 	  first_free=next;
    75 	}
    76 	return cross[n];
    77       }
    78       else {
    79 	///\todo Create an own exception type.
    80 	throw LogicError(); //floatingId-s must form a continuous range;
    81       }
    82     }
    83     ///Remove a fix id.
    84 
    85     ///\param n is a fix id
    86     ///
    87     void erase(int n) 
    88     {
    89       int fl=index[n];
    90       index[n]=first_free;
    91       first_free=n;
    92       for(int i=fl+1;i<int(cross.size());++i) {
    93 	cross[i-1]=cross[i];
    94 	index[cross[i]]--;
    95       }
    96       cross.pop_back();
    97     }
    98     ///An upper bound on the largest fix id.
    99 
   100     ///\todo Do we need this?
   101     ///
   102     std::size_t maxFixId() { return cross.size()-1; }
   103   
   104   };
   105     
   106   ///Common base class for LP solvers
   107   
   108   ///\todo Much more docs
   109   ///\ingroup gen_opt_group
   110   class LpSolverBase {
   111 
   112   public:
   113 
   114     ///Possible outcomes of an LP solving procedure
   115     enum SolveExitStatus {
   116       ///This means that the problem has been successfully solved: either
   117       ///an optimal solution has been found or infeasibility/unboundedness
   118       ///has been proved.
   119       SOLVED = 0,
   120       ///Any other case (including the case when some user specified limit has been exceeded)
   121       UNSOLVED = 1
   122     };
   123       
   124       ///\e
   125     enum SolutionStatus {
   126       ///Feasible solution hasn't been found (but may exist).
   127 
   128       ///\todo NOTFOUND might be a better name.
   129       ///
   130       UNDEFINED = 0,
   131       ///The problem has no feasible solution
   132       INFEASIBLE = 1,
   133       ///Feasible solution found
   134       FEASIBLE = 2,
   135       ///Optimal solution exists and found
   136       OPTIMAL = 3,
   137       ///The cost function is unbounded
   138 
   139       ///\todo Give a feasible solution and an infinite ray (and the
   140       ///corresponding bases)
   141       INFINITE = 4
   142     };
   143 
   144     ///\e The type of the investigated LP problem
   145     enum ProblemTypes {
   146       ///Primal-dual feasible
   147       PRIMAL_DUAL_FEASIBLE = 0,
   148       ///Primal feasible dual infeasible
   149       PRIMAL_FEASIBLE_DUAL_INFEASIBLE = 1,
   150       ///Primal infeasible dual feasible
   151       PRIMAL_INFEASIBLE_DUAL_FEASIBLE = 2,
   152       ///Primal-dual infeasible
   153       PRIMAL_DUAL_INFEASIBLE = 3,
   154       ///Could not determine so far
   155       UNKNOWN = 4
   156     };
   157 
   158     ///The floating point type used by the solver
   159     typedef double Value;
   160     ///The infinity constant
   161     static const Value INF;
   162     ///The not a number constant
   163     static const Value NaN;
   164 
   165     static inline bool isNaN(const Value& v) { return v!=v; }
   166     
   167     ///Refer to a column of the LP.
   168 
   169     ///This type is used to refer to a column of the LP.
   170     ///
   171     ///Its value remains valid and correct even after the addition or erase of
   172     ///other columns.
   173     ///
   174     ///\todo Document what can one do with a Col (INVALID, comparing,
   175     ///it is similar to Node/Edge)
   176     class Col {
   177     protected:
   178       int id;
   179       friend class LpSolverBase;
   180       friend class MipSolverBase;
   181     public:
   182       typedef Value ExprValue;
   183       typedef True LpSolverCol;
   184       Col() {}
   185       Col(const Invalid&) : id(-1) {}
   186       bool operator< (Col c) const  {return id< c.id;}
   187       bool operator> (Col c) const  {return id> c.id;}
   188       bool operator==(Col c) const  {return id==c.id;}
   189       bool operator!=(Col c) const  {return id!=c.id;}
   190     };
   191 
   192     ///Refer to a row of the LP.
   193 
   194     ///This type is used to refer to a row of the LP.
   195     ///
   196     ///Its value remains valid and correct even after the addition or erase of
   197     ///other rows.
   198     ///
   199     ///\todo Document what can one do with a Row (INVALID, comparing,
   200     ///it is similar to Node/Edge)
   201     class Row {
   202     protected:
   203       int id;
   204       friend class LpSolverBase;
   205     public:
   206       typedef Value ExprValue;
   207       typedef True LpSolverRow;
   208       Row() {}
   209       Row(const Invalid&) : id(-1) {}
   210 
   211       bool operator< (Row c) const  {return id< c.id;}
   212       bool operator> (Row c) const  {return id> c.id;}
   213       bool operator==(Row c) const  {return id==c.id;}
   214       bool operator!=(Row c) const  {return id!=c.id;} 
   215    };
   216     
   217     ///Linear expression of variables and a constant component
   218     
   219     ///This data structure strores a linear expression of the variables
   220     ///(\ref Col "Col"s) and also has a constant component.
   221     ///
   222     ///There are several ways to access and modify the contents of this
   223     ///container.
   224     ///- Its it fully compatible with \c std::map<Col,double>, so for expamle
   225     ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can
   226     ///read and modify the coefficients like
   227     ///these.
   228     ///\code
   229     ///e[v]=5;
   230     ///e[v]+=12;
   231     ///e.erase(v);
   232     ///\endcode
   233     ///or you can also iterate through its elements.
   234     ///\code
   235     ///double s=0;
   236     ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i)
   237     ///  s+=i->second;
   238     ///\endcode
   239     ///(This code computes the sum of all coefficients).
   240     ///- Numbers (<tt>double</tt>'s)
   241     ///and variables (\ref Col "Col"s) directly convert to an
   242     ///\ref Expr and the usual linear operations are defined, so  
   243     ///\code
   244     ///v+w
   245     ///2*v-3.12*(v-w/2)+2
   246     ///v*2.1+(3*v+(v*12+w+6)*3)/2
   247     ///\endcode
   248     ///are valid \ref Expr "Expr"essions.
   249     ///The usual assignment operations are also defined.
   250     ///\code
   251     ///e=v+w;
   252     ///e+=2*v-3.12*(v-w/2)+2;
   253     ///e*=3.4;
   254     ///e/=5;
   255     ///\endcode
   256     ///- The constant member can be set and read by \ref constComp()
   257     ///\code
   258     ///e.constComp()=12;
   259     ///double c=e.constComp();
   260     ///\endcode
   261     ///
   262     ///\note \ref clear() not only sets all coefficients to 0 but also
   263     ///clears the constant components.
   264     ///
   265     ///\sa Constr
   266     ///
   267     class Expr : public std::map<Col,Value>
   268     {
   269     public:
   270       typedef LpSolverBase::Col Key; 
   271       typedef LpSolverBase::Value Value;
   272       
   273     protected:
   274       typedef std::map<Col,Value> Base;
   275       
   276       Value const_comp;
   277   public:
   278       typedef True IsLinExpression;
   279       ///\e
   280       Expr() : Base(), const_comp(0) { }
   281       ///\e
   282       Expr(const Key &v) : const_comp(0) {
   283 	Base::insert(std::make_pair(v, 1));
   284       }
   285       ///\e
   286       Expr(const Value &v) : const_comp(v) {}
   287       ///\e
   288       void set(const Key &v,const Value &c) {
   289 	Base::insert(std::make_pair(v, c));
   290       }
   291       ///\e
   292       Value &constComp() { return const_comp; }
   293       ///\e
   294       const Value &constComp() const { return const_comp; }
   295       
   296       ///Removes the components with zero coefficient.
   297       void simplify() {
   298 	for (Base::iterator i=Base::begin(); i!=Base::end();) {
   299 	  Base::iterator j=i;
   300 	  ++j;
   301 	  if ((*i).second==0) Base::erase(i);
   302 	  i=j;
   303 	}
   304       }
   305 
   306       ///Removes the coefficients closer to zero than \c tolerance.
   307       void simplify(double &tolerance) {
   308 	for (Base::iterator i=Base::begin(); i!=Base::end();) {
   309 	  Base::iterator j=i;
   310 	  ++j;
   311 	  if (std::fabs((*i).second)<tolerance) Base::erase(i);
   312 	  i=j;
   313 	}
   314       }
   315 
   316       ///Sets all coefficients and the constant component to 0.
   317       void clear() {
   318 	Base::clear();
   319 	const_comp=0;
   320       }
   321 
   322       ///\e
   323       Expr &operator+=(const Expr &e) {
   324 	for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
   325 	  (*this)[j->first]+=j->second;
   326 	const_comp+=e.const_comp;
   327 	return *this;
   328       }
   329       ///\e
   330       Expr &operator-=(const Expr &e) {
   331 	for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
   332 	  (*this)[j->first]-=j->second;
   333 	const_comp-=e.const_comp;
   334 	return *this;
   335       }
   336       ///\e
   337       Expr &operator*=(const Value &c) {
   338 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   339 	  j->second*=c;
   340 	const_comp*=c;
   341 	return *this;
   342       }
   343       ///\e
   344       Expr &operator/=(const Value &c) {
   345 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   346 	  j->second/=c;
   347 	const_comp/=c;
   348 	return *this;
   349       }
   350     };
   351     
   352     ///Linear constraint
   353 
   354     ///This data stucture represents a linear constraint in the LP.
   355     ///Basically it is a linear expression with a lower or an upper bound
   356     ///(or both). These parts of the constraint can be obtained by the member
   357     ///functions \ref expr(), \ref lowerBound() and \ref upperBound(),
   358     ///respectively.
   359     ///There are two ways to construct a constraint.
   360     ///- You can set the linear expression and the bounds directly
   361     ///  by the functions above.
   362     ///- The operators <tt>\<=</tt>, <tt>==</tt> and  <tt>\>=</tt>
   363     ///  are defined between expressions, or even between constraints whenever
   364     ///  it makes sense. Therefore if \c e and \c f are linear expressions and
   365     ///  \c s and \c t are numbers, then the followings are valid expressions
   366     ///  and thus they can be used directly e.g. in \ref addRow() whenever
   367     ///  it makes sense.
   368     ///\code
   369     ///  e<=s
   370     ///  e<=f
   371     ///  e==f
   372     ///  s<=e<=t
   373     ///  e>=t
   374     ///\endcode
   375     ///\warning The validity of a constraint is checked only at run time, so
   376     ///e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will compile, but will throw a
   377     ///\ref LogicError exception.
   378     class Constr
   379     {
   380     public:
   381       typedef LpSolverBase::Expr Expr;
   382       typedef Expr::Key Key;
   383       typedef Expr::Value Value;
   384       
   385 //       static const Value INF;
   386 //       static const Value NaN;
   387 
   388     protected:
   389       Expr _expr;
   390       Value _lb,_ub;
   391     public:
   392       ///\e
   393       Constr() : _expr(), _lb(NaN), _ub(NaN) {}
   394       ///\e
   395       Constr(Value lb,const Expr &e,Value ub) :
   396 	_expr(e), _lb(lb), _ub(ub) {}
   397       ///\e
   398       Constr(const Expr &e,Value ub) : 
   399 	_expr(e), _lb(NaN), _ub(ub) {}
   400       ///\e
   401       Constr(Value lb,const Expr &e) :
   402 	_expr(e), _lb(lb), _ub(NaN) {}
   403       ///\e
   404       Constr(const Expr &e) : 
   405 	_expr(e), _lb(NaN), _ub(NaN) {}
   406       ///\e
   407       void clear() 
   408       {
   409 	_expr.clear();
   410 	_lb=_ub=NaN;
   411       }
   412 
   413       ///Reference to the linear expression 
   414       Expr &expr() { return _expr; }
   415       ///Cont reference to the linear expression 
   416       const Expr &expr() const { return _expr; }
   417       ///Reference to the lower bound.
   418 
   419       ///\return
   420       ///- \ref INF "INF": the constraint is lower unbounded.
   421       ///- \ref NaN "NaN": lower bound has not been set.
   422       ///- finite number: the lower bound
   423       Value &lowerBound() { return _lb; }
   424       ///The const version of \ref lowerBound()
   425       const Value &lowerBound() const { return _lb; }
   426       ///Reference to the upper bound.
   427 
   428       ///\return
   429       ///- \ref INF "INF": the constraint is upper unbounded.
   430       ///- \ref NaN "NaN": upper bound has not been set.
   431       ///- finite number: the upper bound
   432       Value &upperBound() { return _ub; }
   433       ///The const version of \ref upperBound()
   434       const Value &upperBound() const { return _ub; }
   435       ///Is the constraint lower bounded?
   436       bool lowerBounded() const { 
   437 	using namespace std;
   438 	return finite(_lb);
   439       }
   440       ///Is the constraint upper bounded?
   441       bool upperBounded() const {
   442 	using namespace std;
   443 	return finite(_ub);
   444       }
   445     };
   446     
   447     ///Linear expression of rows
   448     
   449     ///This data structure represents a column of the matrix,
   450     ///thas is it strores a linear expression of the dual variables
   451     ///(\ref Row "Row"s).
   452     ///
   453     ///There are several ways to access and modify the contents of this
   454     ///container.
   455     ///- Its it fully compatible with \c std::map<Row,double>, so for expamle
   456     ///if \c e is an DualExpr and \c v
   457     ///and \c w are of type \ref Row, then you can
   458     ///read and modify the coefficients like
   459     ///these.
   460     ///\code
   461     ///e[v]=5;
   462     ///e[v]+=12;
   463     ///e.erase(v);
   464     ///\endcode
   465     ///or you can also iterate through its elements.
   466     ///\code
   467     ///double s=0;
   468     ///for(LpSolverBase::DualExpr::iterator i=e.begin();i!=e.end();++i)
   469     ///  s+=i->second;
   470     ///\endcode
   471     ///(This code computes the sum of all coefficients).
   472     ///- Numbers (<tt>double</tt>'s)
   473     ///and variables (\ref Row "Row"s) directly convert to an
   474     ///\ref DualExpr and the usual linear operations are defined, so
   475     ///\code
   476     ///v+w
   477     ///2*v-3.12*(v-w/2)
   478     ///v*2.1+(3*v+(v*12+w)*3)/2
   479     ///\endcode
   480     ///are valid \ref DualExpr "DualExpr"essions.
   481     ///The usual assignment operations are also defined.
   482     ///\code
   483     ///e=v+w;
   484     ///e+=2*v-3.12*(v-w/2);
   485     ///e*=3.4;
   486     ///e/=5;
   487     ///\endcode
   488     ///
   489     ///\sa Expr
   490     ///
   491     class DualExpr : public std::map<Row,Value>
   492     {
   493     public:
   494       typedef LpSolverBase::Row Key; 
   495       typedef LpSolverBase::Value Value;
   496       
   497     protected:
   498       typedef std::map<Row,Value> Base;
   499       
   500     public:
   501       typedef True IsLinExpression;
   502       ///\e
   503       DualExpr() : Base() { }
   504       ///\e
   505       DualExpr(const Key &v) {
   506 	Base::insert(std::make_pair(v, 1));
   507       }
   508       ///\e
   509       void set(const Key &v,const Value &c) {
   510 	Base::insert(std::make_pair(v, c));
   511       }
   512       
   513       ///Removes the components with zero coefficient.
   514       void simplify() {
   515 	for (Base::iterator i=Base::begin(); i!=Base::end();) {
   516 	  Base::iterator j=i;
   517 	  ++j;
   518 	  if ((*i).second==0) Base::erase(i);
   519 	  i=j;
   520 	}
   521       }
   522 
   523       ///Removes the coefficients closer to zero than \c tolerance.
   524       void simplify(double &tolerance) {
   525 	for (Base::iterator i=Base::begin(); i!=Base::end();) {
   526 	  Base::iterator j=i;
   527 	  ++j;
   528 	  if (std::fabs((*i).second)<tolerance) Base::erase(i);
   529 	  i=j;
   530 	}
   531       }
   532 
   533 
   534       ///Sets all coefficients to 0.
   535       void clear() {
   536 	Base::clear();
   537       }
   538 
   539       ///\e
   540       DualExpr &operator+=(const DualExpr &e) {
   541 	for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
   542 	  (*this)[j->first]+=j->second;
   543 	return *this;
   544       }
   545       ///\e
   546       DualExpr &operator-=(const DualExpr &e) {
   547 	for (Base::const_iterator j=e.begin(); j!=e.end(); ++j)
   548 	  (*this)[j->first]-=j->second;
   549 	return *this;
   550       }
   551       ///\e
   552       DualExpr &operator*=(const Value &c) {
   553 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   554 	  j->second*=c;
   555 	return *this;
   556       }
   557       ///\e
   558       DualExpr &operator/=(const Value &c) {
   559 	for (Base::iterator j=Base::begin(); j!=Base::end(); ++j)
   560 	  j->second/=c;
   561 	return *this;
   562       }
   563     };
   564     
   565 
   566   protected:
   567     _FixId rows;
   568     _FixId cols;
   569 
   570     //Abstract virtual functions
   571     virtual LpSolverBase &_newLp() = 0;
   572     virtual LpSolverBase &_copyLp(){
   573       ///\todo This should be implemented here, too,  when we have problem retrieving routines. It can be overriden.
   574 
   575       //Starting:
   576       LpSolverBase & newlp(_newLp());
   577       return newlp;
   578       //return *(LpSolverBase*)0;
   579     };
   580 
   581     virtual int _addCol() = 0;
   582     virtual int _addRow() = 0;
   583     virtual void _eraseCol(int col) = 0;
   584     virtual void _eraseRow(int row) = 0;
   585     virtual void _getColName(int col,       std::string & name) = 0;
   586     virtual void _setColName(int col, const std::string & name) = 0;
   587     virtual void _setRowCoeffs(int i, 
   588 			       int length,
   589                                int  const * indices, 
   590                                Value  const * values ) = 0;
   591     virtual void _setColCoeffs(int i, 
   592 			       int length,
   593                                int  const * indices, 
   594                                Value  const * values ) = 0;
   595     virtual void _setCoeff(int row, int col, Value value) = 0;
   596     virtual void _setColLowerBound(int i, Value value) = 0;
   597     virtual void _setColUpperBound(int i, Value value) = 0;
   598 //     virtual void _setRowLowerBound(int i, Value value) = 0;
   599 //     virtual void _setRowUpperBound(int i, Value value) = 0;
   600     virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
   601     virtual void _setObjCoeff(int i, Value obj_coef) = 0;
   602     virtual void _clearObj()=0;
   603 //     virtual void _setObj(int length,
   604 //                          int  const * indices, 
   605 //                          Value  const * values ) = 0;
   606     virtual SolveExitStatus _solve() = 0;
   607     virtual Value _getPrimal(int i) = 0;
   608     virtual Value _getDual(int i) = 0;
   609     virtual Value _getPrimalValue() = 0;
   610     virtual bool _isBasicCol(int i) = 0;
   611     virtual SolutionStatus _getPrimalStatus() = 0;
   612     virtual SolutionStatus _getDualStatus() = 0;
   613     ///\todo This could be implemented here, too, using _getPrimalStatus() and
   614     ///_getDualStatus()
   615     virtual ProblemTypes _getProblemType() = 0;
   616 
   617     virtual void _setMax() = 0;
   618     virtual void _setMin() = 0;
   619     
   620     //Own protected stuff
   621     
   622     //Constant component of the objective function
   623     Value obj_const_comp;
   624     
   625 
   626 
   627     
   628   public:
   629 
   630     ///\e
   631     LpSolverBase() : obj_const_comp(0) {}
   632 
   633     ///\e
   634     virtual ~LpSolverBase() {}
   635 
   636     ///Creates a new LP problem
   637     LpSolverBase &newLp() {return _newLp();}
   638     ///Makes a copy of the LP problem
   639     LpSolverBase &copyLp() {return _copyLp();}
   640     
   641     ///\name Build up and modify the LP
   642 
   643     ///@{
   644 
   645     ///Add a new empty column (i.e a new variable) to the LP
   646     Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
   647 
   648     ///\brief Adds several new columns
   649     ///(i.e a variables) at once
   650     ///
   651     ///This magic function takes a container as its argument
   652     ///and fills its elements
   653     ///with new columns (i.e. variables)
   654     ///\param t can be
   655     ///- a standard STL compatible iterable container with
   656     ///\ref Col as its \c values_type
   657     ///like
   658     ///\code
   659     ///std::vector<LpSolverBase::Col>
   660     ///std::list<LpSolverBase::Col>
   661     ///\endcode
   662     ///- a standard STL compatible iterable container with
   663     ///\ref Col as its \c mapped_type
   664     ///like
   665     ///\code
   666     ///std::map<AnyType,LpSolverBase::Col>
   667     ///\endcode
   668     ///- an iterable lemon \ref concept::WriteMap "write map" like 
   669     ///\code
   670     ///ListGraph::NodeMap<LpSolverBase::Col>
   671     ///ListGraph::EdgeMap<LpSolverBase::Col>
   672     ///\endcode
   673     ///\return The number of the created column.
   674 #ifdef DOXYGEN
   675     template<class T>
   676     int addColSet(T &t) { return 0;} 
   677 #else
   678     template<class T>
   679     typename enable_if<typename T::value_type::LpSolverCol,int>::type
   680     addColSet(T &t,dummy<0> = 0) {
   681       int s=0;
   682       for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
   683       return s;
   684     }
   685     template<class T>
   686     typename enable_if<typename T::value_type::second_type::LpSolverCol,
   687 		       int>::type
   688     addColSet(T &t,dummy<1> = 1) { 
   689       int s=0;
   690       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   691 	i->second=addCol();
   692 	s++;
   693       }
   694       return s;
   695     }
   696     template<class T>
   697     typename enable_if<typename T::MapIt::Value::LpSolverCol,
   698 		       int>::type
   699     addColSet(T &t,dummy<2> = 2) { 
   700       int s=0;
   701       for(typename T::MapIt i(t); i!=INVALID; ++i)
   702 	{
   703 	  i.set(addCol());
   704 	  s++;
   705 	}
   706       return s;
   707     }
   708 #endif
   709 
   710     ///Set a column (i.e a dual constraint) of the LP
   711 
   712     ///\param c is the column to be modified
   713     ///\param e is a dual linear expression (see \ref DualExpr)
   714     ///a better one.
   715     void col(Col c,const DualExpr &e) {
   716       std::vector<int> indices;
   717       std::vector<Value> values;
   718       indices.push_back(0);
   719       values.push_back(0);
   720       for(DualExpr::const_iterator i=e.begin(); i!=e.end(); ++i)
   721 	if((*i).second!=0) {
   722 	  indices.push_back(rows.floatingId((*i).first.id));
   723 	  values.push_back((*i).second);
   724 	}
   725       _setColCoeffs(cols.floatingId(c.id),indices.size()-1,
   726 		    &indices[0],&values[0]);
   727     }
   728 
   729     ///Add a new column to the LP
   730 
   731     ///\param e is a dual linear expression (see \ref DualExpr)
   732     ///\param obj is the corresponding component of the objective
   733     ///function. It is 0 by default.
   734     ///\return The created column.
   735     Col addCol(const DualExpr &e, Value obj=0) {
   736       Col c=addCol();
   737       col(c,e);
   738       objCoeff(c,obj);
   739       return c;
   740     }
   741 
   742     ///Add a new empty row (i.e a new constraint) to the LP
   743 
   744     ///This function adds a new empty row (i.e a new constraint) to the LP.
   745     ///\return The created row
   746     Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
   747 
   748     ///\brief Add several new rows
   749     ///(i.e a constraints) at once
   750     ///
   751     ///This magic function takes a container as its argument
   752     ///and fills its elements
   753     ///with new row (i.e. variables)
   754     ///\param t can be
   755     ///- a standard STL compatible iterable container with
   756     ///\ref Row as its \c values_type
   757     ///like
   758     ///\code
   759     ///std::vector<LpSolverBase::Row>
   760     ///std::list<LpSolverBase::Row>
   761     ///\endcode
   762     ///- a standard STL compatible iterable container with
   763     ///\ref Row as its \c mapped_type
   764     ///like
   765     ///\code
   766     ///std::map<AnyType,LpSolverBase::Row>
   767     ///\endcode
   768     ///- an iterable lemon \ref concept::WriteMap "write map" like 
   769     ///\code
   770     ///ListGraph::NodeMap<LpSolverBase::Row>
   771     ///ListGraph::EdgeMap<LpSolverBase::Row>
   772     ///\endcode
   773     ///\return The number of rows created.
   774 #ifdef DOXYGEN
   775     template<class T>
   776     int addRowSet(T &t) { return 0;} 
   777 #else
   778     template<class T>
   779     typename enable_if<typename T::value_type::LpSolverRow,int>::type
   780     addRowSet(T &t,dummy<0> = 0) {
   781       int s=0;
   782       for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
   783       return s;
   784     }
   785     template<class T>
   786     typename enable_if<typename T::value_type::second_type::LpSolverRow,
   787 		       int>::type
   788     addRowSet(T &t,dummy<1> = 1) { 
   789       int s=0;
   790       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   791 	i->second=addRow();
   792 	s++;
   793       }
   794       return s;
   795     }
   796     template<class T>
   797     typename enable_if<typename T::MapIt::Value::LpSolverRow,
   798 		       int>::type
   799     addRowSet(T &t,dummy<2> = 2) { 
   800       int s=0;
   801       for(typename T::MapIt i(t); i!=INVALID; ++i)
   802 	{
   803 	  i.set(addRow());
   804 	  s++;
   805 	}
   806       return s;
   807     }
   808 #endif
   809 
   810     ///Set a row (i.e a constraint) of the LP
   811 
   812     ///\param r is the row to be modified
   813     ///\param l is lower bound (-\ref INF means no bound)
   814     ///\param e is a linear expression (see \ref Expr)
   815     ///\param u is the upper bound (\ref INF means no bound)
   816     ///\bug This is a temportary function. The interface will change to
   817     ///a better one.
   818     ///\todo Option to control whether a constraint with a single variable is
   819     ///added or not.
   820     void row(Row r, Value l,const Expr &e, Value u) {
   821       std::vector<int> indices;
   822       std::vector<Value> values;
   823       indices.push_back(0);
   824       values.push_back(0);
   825       for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
   826 	if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
   827 	  indices.push_back(cols.floatingId((*i).first.id));
   828 	  values.push_back((*i).second);
   829 	}
   830       _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
   831 		    &indices[0],&values[0]);
   832 //       _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
   833 //       _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
   834        _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp());
   835     }
   836 
   837     ///Set a row (i.e a constraint) of the LP
   838 
   839     ///\param r is the row to be modified
   840     ///\param c is a linear expression (see \ref Constr)
   841     void row(Row r, const Constr &c) {
   842       row(r,
   843 	     c.lowerBounded()?c.lowerBound():-INF,
   844 	     c.expr(),
   845 	     c.upperBounded()?c.upperBound():INF);
   846     }
   847 
   848     ///Add a new row (i.e a new constraint) to the LP
   849 
   850     ///\param l is the lower bound (-\ref INF means no bound)
   851     ///\param e is a linear expression (see \ref Expr)
   852     ///\param u is the upper bound (\ref INF means no bound)
   853     ///\return The created row.
   854     ///\bug This is a temportary function. The interface will change to
   855     ///a better one.
   856     Row addRow(Value l,const Expr &e, Value u) {
   857       Row r=addRow();
   858       row(r,l,e,u);
   859       return r;
   860     }
   861 
   862     ///Add a new row (i.e a new constraint) to the LP
   863 
   864     ///\param c is a linear expression (see \ref Constr)
   865     ///\return The created row.
   866     Row addRow(const Constr &c) {
   867       Row r=addRow();
   868       row(r,c);
   869       return r;
   870     }
   871     ///Erase a coloumn (i.e a variable) from the LP
   872 
   873     ///\param c is the coloumn to be deleted
   874     ///\todo Please check this
   875     void eraseCol(Col c) {
   876       _eraseCol(cols.floatingId(c.id));
   877       cols.erase(c.id);
   878     }
   879     ///Erase a  row (i.e a constraint) from the LP
   880 
   881     ///\param r is the row to be deleted
   882     ///\todo Please check this
   883     void eraseRow(Row r) {
   884       _eraseRow(rows.floatingId(r.id));
   885       rows.erase(r.id);
   886     }
   887 
   888     /// Get the name of a column
   889     
   890     ///\param c is the coresponding coloumn 
   891     ///\return The name of the colunm
   892     std::string ColName(Col c){
   893       std::string name;
   894       _getColName(cols.floatingId(c.id), name);
   895       return name;
   896     }
   897     
   898     /// Set the name of a column
   899     
   900     ///\param c is the coresponding coloumn 
   901     ///\param name The name to be given
   902     void ColName(Col c, const std::string & name){
   903       _setColName(cols.floatingId(c.id), name);
   904     }
   905     
   906     /// Set an element of the coefficient matrix of the LP
   907 
   908     ///\param r is the row of the element to be modified
   909     ///\param c is the coloumn of the element to be modified
   910     ///\param val is the new value of the coefficient
   911 
   912     void Coeff(Row r, Col c, Value val){
   913       _setCoeff(rows.floatingId(r.id),cols.floatingId(c.id), val);
   914     }
   915 
   916     /// Set the lower bound of a column (i.e a variable)
   917 
   918     /// The lower bound of a variable (column) has to be given by an 
   919     /// extended number of type Value, i.e. a finite number of type 
   920     /// Value or -\ref INF.
   921     void colLowerBound(Col c, Value value) {
   922       _setColLowerBound(cols.floatingId(c.id),value);
   923     }
   924     
   925     ///\brief Set the lower bound of  several columns
   926     ///(i.e a variables) at once
   927     ///
   928     ///This magic function takes a container as its argument
   929     ///and applies the function on all of its elements.
   930     /// The lower bound of a variable (column) has to be given by an 
   931     /// extended number of type Value, i.e. a finite number of type 
   932     /// Value or -\ref INF.
   933 #ifdef DOXYGEN
   934     template<class T>
   935     void colLowerBound(T &t, Value value) { return 0;} 
   936 #else
   937     template<class T>
   938     typename enable_if<typename T::value_type::LpSolverCol,void>::type
   939     colLowerBound(T &t, Value value,dummy<0> = 0) {
   940       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   941 	colLowerBound(*i, value);
   942       }
   943     }
   944     template<class T>
   945     typename enable_if<typename T::value_type::second_type::LpSolverCol,
   946 		       void>::type
   947     colLowerBound(T &t, Value value,dummy<1> = 1) { 
   948       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   949 	colLowerBound(i->second, value);
   950       }
   951     }
   952     template<class T>
   953     typename enable_if<typename T::MapIt::Value::LpSolverCol,
   954 		       void>::type
   955     colLowerBound(T &t, Value value,dummy<2> = 2) { 
   956       for(typename T::MapIt i(t); i!=INVALID; ++i){
   957 	colLowerBound(*i, value);
   958       }
   959     }
   960 #endif
   961     
   962     /// Set the upper bound of a column (i.e a variable)
   963 
   964     /// The upper bound of a variable (column) has to be given by an 
   965     /// extended number of type Value, i.e. a finite number of type 
   966     /// Value or \ref INF.
   967     void colUpperBound(Col c, Value value) {
   968       _setColUpperBound(cols.floatingId(c.id),value);
   969     };
   970 
   971     ///\brief Set the lower bound of  several columns
   972     ///(i.e a variables) at once
   973     ///
   974     ///This magic function takes a container as its argument
   975     ///and applies the function on all of its elements.
   976     /// The upper bound of a variable (column) has to be given by an 
   977     /// extended number of type Value, i.e. a finite number of type 
   978     /// Value or \ref INF.
   979 #ifdef DOXYGEN
   980     template<class T>
   981     void colUpperBound(T &t, Value value) { return 0;} 
   982 #else
   983     template<class T>
   984     typename enable_if<typename T::value_type::LpSolverCol,void>::type
   985     colUpperBound(T &t, Value value,dummy<0> = 0) {
   986       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   987 	colUpperBound(*i, value);
   988       }
   989     }
   990     template<class T>
   991     typename enable_if<typename T::value_type::second_type::LpSolverCol,
   992 		       void>::type
   993     colUpperBound(T &t, Value value,dummy<1> = 1) { 
   994       for(typename T::iterator i=t.begin();i!=t.end();++i) {
   995 	colUpperBound(i->second, value);
   996       }
   997     }
   998     template<class T>
   999     typename enable_if<typename T::MapIt::Value::LpSolverCol,
  1000 		       void>::type
  1001     colUpperBound(T &t, Value value,dummy<2> = 2) { 
  1002       for(typename T::MapIt i(t); i!=INVALID; ++i){
  1003 	colUpperBound(*i, value);
  1004       }
  1005     }
  1006 #endif
  1007 
  1008     /// Set the lower and the upper bounds of a column (i.e a variable)
  1009 
  1010     /// The lower and the upper bounds of
  1011     /// a variable (column) have to be given by an 
  1012     /// extended number of type Value, i.e. a finite number of type 
  1013     /// Value, -\ref INF or \ref INF.
  1014     void colBounds(Col c, Value lower, Value upper) {
  1015       _setColLowerBound(cols.floatingId(c.id),lower);
  1016       _setColUpperBound(cols.floatingId(c.id),upper);
  1017     }
  1018     
  1019     ///\brief Set the lower and the upper bound of several columns
  1020     ///(i.e a variables) at once
  1021     ///
  1022     ///This magic function takes a container as its argument
  1023     ///and applies the function on all of its elements.
  1024     /// The lower and the upper bounds of
  1025     /// a variable (column) have to be given by an 
  1026     /// extended number of type Value, i.e. a finite number of type 
  1027     /// Value, -\ref INF or \ref INF.
  1028 #ifdef DOXYGEN
  1029     template<class T>
  1030     void colBounds(T &t, Value lower, Value upper) { return 0;} 
  1031 #else
  1032     template<class T>
  1033     typename enable_if<typename T::value_type::LpSolverCol,void>::type
  1034     colBounds(T &t, Value lower, Value upper,dummy<0> = 0) {
  1035       for(typename T::iterator i=t.begin();i!=t.end();++i) {
  1036 	colBounds(*i, lower, upper);
  1037       }
  1038     }
  1039     template<class T>
  1040     typename enable_if<typename T::value_type::second_type::LpSolverCol,
  1041 		       void>::type
  1042     colBounds(T &t, Value lower, Value upper,dummy<1> = 1) { 
  1043       for(typename T::iterator i=t.begin();i!=t.end();++i) {
  1044 	colBounds(i->second, lower, upper);
  1045       }
  1046     }
  1047     template<class T>
  1048     typename enable_if<typename T::MapIt::Value::LpSolverCol,
  1049 		       void>::type
  1050     colBounds(T &t, Value lower, Value upper,dummy<2> = 2) { 
  1051       for(typename T::MapIt i(t); i!=INVALID; ++i){
  1052 	colBounds(*i, lower, upper);
  1053       }
  1054     }
  1055 #endif
  1056     
  1057 //     /// Set the lower bound of a row (i.e a constraint)
  1058 
  1059 //     /// The lower bound of a linear expression (row) has to be given by an 
  1060 //     /// extended number of type Value, i.e. a finite number of type 
  1061 //     /// Value or -\ref INF.
  1062 //     void rowLowerBound(Row r, Value value) {
  1063 //       _setRowLowerBound(rows.floatingId(r.id),value);
  1064 //     };
  1065 //     /// Set the upper bound of a row (i.e a constraint)
  1066 
  1067 //     /// The upper bound of a linear expression (row) has to be given by an 
  1068 //     /// extended number of type Value, i.e. a finite number of type 
  1069 //     /// Value or \ref INF.
  1070 //     void rowUpperBound(Row r, Value value) {
  1071 //       _setRowUpperBound(rows.floatingId(r.id),value);
  1072 //     };
  1073 
  1074     /// Set the lower and the upper bounds of a row (i.e a constraint)
  1075 
  1076     /// The lower and the upper bounds of
  1077     /// a constraint (row) have to be given by an 
  1078     /// extended number of type Value, i.e. a finite number of type 
  1079     /// Value, -\ref INF or \ref INF.
  1080     void rowBounds(Row c, Value lower, Value upper) {
  1081       _setRowBounds(rows.floatingId(c.id),lower, upper);
  1082       // _setRowUpperBound(rows.floatingId(c.id),upper);
  1083     }
  1084     
  1085     ///Set an element of the objective function
  1086     void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
  1087     ///Set the objective function
  1088     
  1089     ///\param e is a linear expression of type \ref Expr.
  1090     ///\bug Is should be called obj()
  1091     void setObj(Expr e) {
  1092       _clearObj();
  1093       for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
  1094 	objCoeff((*i).first,(*i).second);
  1095       obj_const_comp=e.constComp();
  1096     }
  1097 
  1098     ///Maximize
  1099     void max() { _setMax(); }
  1100     ///Minimize
  1101     void min() { _setMin(); }
  1102 
  1103     
  1104     ///@}
  1105 
  1106 
  1107     ///\name Solve the LP
  1108 
  1109     ///@{
  1110 
  1111     ///\e Solve the LP problem at hand
  1112     ///
  1113     ///\return The result of the optimization procedure. Possible 
  1114     ///values and their meanings can be found in the documentation of 
  1115     ///\ref SolveExitStatus.
  1116     ///
  1117     ///\todo Which method is used to solve the problem
  1118     SolveExitStatus solve() { return _solve(); }
  1119     
  1120     ///@}
  1121     
  1122     ///\name Obtain the solution
  1123 
  1124     ///@{
  1125 
  1126     /// The status of the primal problem (the original LP problem)
  1127     SolutionStatus primalStatus() {
  1128       return _getPrimalStatus();
  1129     }
  1130 
  1131     /// The status of the dual (of the original LP) problem 
  1132     SolutionStatus dualStatus() {
  1133       return _getDualStatus();
  1134     }
  1135 
  1136     ///The type of the original LP problem
  1137     ProblemTypes problemType() {
  1138       return _getProblemType();
  1139     }
  1140 
  1141     ///\e
  1142     Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); }
  1143 
  1144     ///\e
  1145     Value dual(Row r) { return _getDual(rows.floatingId(r.id)); }
  1146 
  1147     ///\e
  1148     bool isBasicCol(Col c) { return _isBasicCol(cols.floatingId(c.id)); }
  1149 
  1150     ///\e
  1151 
  1152     ///\return
  1153     ///- \ref INF or -\ref INF means either infeasibility or unboundedness
  1154     /// of the primal problem, depending on whether we minimize or maximize.
  1155     ///- \ref NaN if no primal solution is found.
  1156     ///- The (finite) objective value if an optimal solution is found.
  1157     Value primalValue() { return _getPrimalValue()+obj_const_comp;}
  1158     ///@}
  1159     
  1160   };  
  1161 
  1162 
  1163   ///Common base class for MIP solvers
  1164   ///\todo Much more docs
  1165   ///\ingroup gen_opt_group
  1166   class MipSolverBase : virtual public LpSolverBase{
  1167   public:
  1168 
  1169     ///Possible variable (coloumn) types (e.g. real, integer, binary etc.)
  1170     enum ColTypes {
  1171       ///Continuous variable
  1172       REAL = 0,
  1173       ///Integer variable
  1174 
  1175       ///Unfortunately, cplex 7.5 somewhere writes something like
  1176       ///#define INTEGER 'I'
  1177       LEMON_INTEGER = 1
  1178       ///\todo No support for other types yet.
  1179     };
  1180 
  1181     ///Sets the type of the given coloumn to the given type
  1182     ///
  1183     ///Sets the type of the given coloumn to the given type.
  1184     void colType(Col c, ColTypes col_type) {
  1185       _colType(cols.floatingId(c.id),col_type);
  1186     }
  1187 
  1188     ///Gives back the type of the column.
  1189     ///
  1190     ///Gives back the type of the column.
  1191     ColTypes colType(Col c){
  1192       return _colType(cols.floatingId(c.id));
  1193     }
  1194 
  1195     ///Sets the type of the given Col to integer or remove that property.
  1196     ///
  1197     ///Sets the type of the given Col to integer or remove that property.
  1198     void integer(Col c, bool enable) {
  1199       if (enable)
  1200 	colType(c,LEMON_INTEGER);
  1201       else
  1202 	colType(c,REAL);
  1203     }
  1204 
  1205     ///Gives back whether the type of the column is integer or not.
  1206     ///
  1207     ///Gives back the type of the column.
  1208     ///\return true if the column has integer type and false if not.
  1209     bool integer(Col c){
  1210       return (colType(c)==LEMON_INTEGER);
  1211     }
  1212 
  1213     /// The status of the MIP problem
  1214     SolutionStatus mipStatus() {
  1215       return _getMipStatus();
  1216     }
  1217 
  1218   protected:
  1219 
  1220     virtual ColTypes _colType(int col) = 0;
  1221     virtual void _colType(int col, ColTypes col_type) = 0;
  1222     virtual SolutionStatus _getMipStatus()=0;
  1223 
  1224   };
  1225   
  1226   ///\relates LpSolverBase::Expr
  1227   ///
  1228   inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a,
  1229 				      const LpSolverBase::Expr &b) 
  1230   {
  1231     LpSolverBase::Expr tmp(a);
  1232     tmp+=b;
  1233     return tmp;
  1234   }
  1235   ///\e
  1236   
  1237   ///\relates LpSolverBase::Expr
  1238   ///
  1239   inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a,
  1240 				      const LpSolverBase::Expr &b) 
  1241   {
  1242     LpSolverBase::Expr tmp(a);
  1243     tmp-=b;
  1244     return tmp;
  1245   }
  1246   ///\e
  1247   
  1248   ///\relates LpSolverBase::Expr
  1249   ///
  1250   inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a,
  1251 				      const LpSolverBase::Value &b) 
  1252   {
  1253     LpSolverBase::Expr tmp(a);
  1254     tmp*=b;
  1255     return tmp;
  1256   }
  1257   
  1258   ///\e
  1259   
  1260   ///\relates LpSolverBase::Expr
  1261   ///
  1262   inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a,
  1263 				      const LpSolverBase::Expr &b) 
  1264   {
  1265     LpSolverBase::Expr tmp(b);
  1266     tmp*=a;
  1267     return tmp;
  1268   }
  1269   ///\e
  1270   
  1271   ///\relates LpSolverBase::Expr
  1272   ///
  1273   inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a,
  1274 				      const LpSolverBase::Value &b) 
  1275   {
  1276     LpSolverBase::Expr tmp(a);
  1277     tmp/=b;
  1278     return tmp;
  1279   }
  1280   
  1281   ///\e
  1282   
  1283   ///\relates LpSolverBase::Constr
  1284   ///
  1285   inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
  1286 					 const LpSolverBase::Expr &f) 
  1287   {
  1288     return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0);
  1289   }
  1290 
  1291   ///\e
  1292   
  1293   ///\relates LpSolverBase::Constr
  1294   ///
  1295   inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e,
  1296 					 const LpSolverBase::Expr &f) 
  1297   {
  1298     return LpSolverBase::Constr(e,f);
  1299   }
  1300 
  1301   ///\e
  1302   
  1303   ///\relates LpSolverBase::Constr
  1304   ///
  1305   inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e,
  1306 					 const LpSolverBase::Value &f) 
  1307   {
  1308     return LpSolverBase::Constr(e,f);
  1309   }
  1310 
  1311   ///\e
  1312   
  1313   ///\relates LpSolverBase::Constr
  1314   ///
  1315   inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
  1316 					 const LpSolverBase::Expr &f) 
  1317   {
  1318     return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0);
  1319   }
  1320 
  1321 
  1322   ///\e
  1323   
  1324   ///\relates LpSolverBase::Constr
  1325   ///
  1326   inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e,
  1327 					 const LpSolverBase::Expr &f) 
  1328   {
  1329     return LpSolverBase::Constr(f,e);
  1330   }
  1331 
  1332 
  1333   ///\e
  1334   
  1335   ///\relates LpSolverBase::Constr
  1336   ///
  1337   inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e,
  1338 					 const LpSolverBase::Value &f) 
  1339   {
  1340     return LpSolverBase::Constr(f,e);
  1341   }
  1342 
  1343   ///\e
  1344   
  1345   ///\relates LpSolverBase::Constr
  1346   ///
  1347   inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e,
  1348 					 const LpSolverBase::Expr &f) 
  1349   {
  1350     return LpSolverBase::Constr(0,e-f,0);
  1351   }
  1352 
  1353   ///\e
  1354   
  1355   ///\relates LpSolverBase::Constr
  1356   ///
  1357   inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n,
  1358 					 const LpSolverBase::Constr&c) 
  1359   {
  1360     LpSolverBase::Constr tmp(c);
  1361     ///\todo Create an own exception type.
  1362     if(!LpSolverBase::isNaN(tmp.lowerBound())) throw LogicError();
  1363     else tmp.lowerBound()=n;
  1364     return tmp;
  1365   }
  1366   ///\e
  1367   
  1368   ///\relates LpSolverBase::Constr
  1369   ///
  1370   inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c,
  1371 					 const LpSolverBase::Value &n)
  1372   {
  1373     LpSolverBase::Constr tmp(c);
  1374     ///\todo Create an own exception type.
  1375     if(!LpSolverBase::isNaN(tmp.upperBound())) throw LogicError();
  1376     else tmp.upperBound()=n;
  1377     return tmp;
  1378   }
  1379 
  1380   ///\e
  1381   
  1382   ///\relates LpSolverBase::Constr
  1383   ///
  1384   inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n,
  1385 					 const LpSolverBase::Constr&c) 
  1386   {
  1387     LpSolverBase::Constr tmp(c);
  1388     ///\todo Create an own exception type.
  1389     if(!LpSolverBase::isNaN(tmp.upperBound())) throw LogicError();
  1390     else tmp.upperBound()=n;
  1391     return tmp;
  1392   }
  1393   ///\e
  1394   
  1395   ///\relates LpSolverBase::Constr
  1396   ///
  1397   inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c,
  1398 					 const LpSolverBase::Value &n)
  1399   {
  1400     LpSolverBase::Constr tmp(c);
  1401     ///\todo Create an own exception type.
  1402     if(!LpSolverBase::isNaN(tmp.lowerBound())) throw LogicError();
  1403     else tmp.lowerBound()=n;
  1404     return tmp;
  1405   }
  1406 
  1407   ///\e
  1408   
  1409   ///\relates LpSolverBase::DualExpr
  1410   ///
  1411   inline LpSolverBase::DualExpr operator+(const LpSolverBase::DualExpr &a,
  1412 				      const LpSolverBase::DualExpr &b) 
  1413   {
  1414     LpSolverBase::DualExpr tmp(a);
  1415     tmp+=b;
  1416     return tmp;
  1417   }
  1418   ///\e
  1419   
  1420   ///\relates LpSolverBase::DualExpr
  1421   ///
  1422   inline LpSolverBase::DualExpr operator-(const LpSolverBase::DualExpr &a,
  1423 				      const LpSolverBase::DualExpr &b) 
  1424   {
  1425     LpSolverBase::DualExpr tmp(a);
  1426     tmp-=b;
  1427     return tmp;
  1428   }
  1429   ///\e
  1430   
  1431   ///\relates LpSolverBase::DualExpr
  1432   ///
  1433   inline LpSolverBase::DualExpr operator*(const LpSolverBase::DualExpr &a,
  1434 				      const LpSolverBase::Value &b) 
  1435   {
  1436     LpSolverBase::DualExpr tmp(a);
  1437     tmp*=b;
  1438     return tmp;
  1439   }
  1440   
  1441   ///\e
  1442   
  1443   ///\relates LpSolverBase::DualExpr
  1444   ///
  1445   inline LpSolverBase::DualExpr operator*(const LpSolverBase::Value &a,
  1446 				      const LpSolverBase::DualExpr &b) 
  1447   {
  1448     LpSolverBase::DualExpr tmp(b);
  1449     tmp*=a;
  1450     return tmp;
  1451   }
  1452   ///\e
  1453   
  1454   ///\relates LpSolverBase::DualExpr
  1455   ///
  1456   inline LpSolverBase::DualExpr operator/(const LpSolverBase::DualExpr &a,
  1457 				      const LpSolverBase::Value &b) 
  1458   {
  1459     LpSolverBase::DualExpr tmp(a);
  1460     tmp/=b;
  1461     return tmp;
  1462   }
  1463   
  1464 
  1465 } //namespace lemon
  1466 
  1467 #endif //LEMON_LP_BASE_H