COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_base.h @ 2309:468a525d5b45

Last change on this file since 2309:468a525d5b45 was 2309:468a525d5b45, checked in by Alpar Juttner, 17 years ago

Make the constructors of ColIt? public.

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