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