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