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