COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_base.h @ 2000:ebcc93ead7da

Last change on this file since 2000:ebcc93ead7da was 1993:2115143eceea, checked in by Balazs Dezso, 18 years ago

utility, invalid and traits moved to bits

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