src/work/athos/lp/lp_base.h
author marci
Mon, 28 Mar 2005 23:34:26 +0000
changeset 1269 4c63ff4e16fa
parent 1263 a490938ad0aa
child 1272 17be4c5bc6c6
permissions -rw-r--r--
bug fix in SubBidirGraphWrapper::firstIn(Edge&,const Node&), due to Gabor Retvari
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@1256
    21
#include<limits>
alpar@1253
    22
alpar@1256
    23
#include<lemon/utility.h>
alpar@1253
    24
#include<lemon/error.h>
alpar@1256
    25
#include<lemon/invalid.h>
alpar@1253
    26
alpar@1253
    27
#include"lin_expr.h"
athos@1246
    28
///\file
athos@1246
    29
///\brief The interface of the LP solver interface.
athos@1246
    30
namespace lemon {
alpar@1253
    31
  
alpar@1253
    32
  ///Internal data structure to convert floating id's to fix one's
alpar@1253
    33
    
alpar@1253
    34
  ///\todo This might by implemented to be usable in other places.
alpar@1253
    35
  class _FixId 
alpar@1253
    36
  {
alpar@1253
    37
    std::vector<int> index;
alpar@1253
    38
    std::vector<int> cross;
alpar@1253
    39
    int first_free;
alpar@1253
    40
  public:
alpar@1253
    41
    _FixId() : first_free(-1) {};
alpar@1253
    42
    ///Convert a floating id to a fix one
alpar@1253
    43
alpar@1253
    44
    ///\param n is a floating id
alpar@1253
    45
    ///\return the corresponding fix id
alpar@1253
    46
    int fixId(int n) {return cross[n];}
alpar@1253
    47
    ///Convert a fix id to a floating one
alpar@1253
    48
alpar@1253
    49
    ///\param n is a fix id
alpar@1253
    50
    ///\return the corresponding floating id
alpar@1253
    51
    int floatingId(int n) { return index[n];}
alpar@1253
    52
    ///Add a new floating id.
alpar@1253
    53
alpar@1253
    54
    ///\param n is a floating id
alpar@1253
    55
    ///\return the fix id of the new value
alpar@1253
    56
    ///\todo Multiple additions should also be handled.
alpar@1253
    57
    int insert(int n)
alpar@1253
    58
    {
alpar@1253
    59
      if(n>=int(cross.size())) {
alpar@1253
    60
	cross.resize(n+1);
alpar@1253
    61
	if(first_free==-1) {
alpar@1253
    62
	  cross[n]=index.size();
alpar@1253
    63
	  index.push_back(n);
alpar@1253
    64
	}
alpar@1253
    65
	else {
alpar@1253
    66
	  cross[n]=first_free;
alpar@1253
    67
	  int next=index[first_free];
alpar@1253
    68
	  index[first_free]=n;
alpar@1253
    69
	  first_free=next;
alpar@1253
    70
	}
alpar@1256
    71
	return cross[n];
alpar@1253
    72
      }
alpar@1253
    73
      else throw LogicError(); //floatingId-s must form a continuous range;
alpar@1253
    74
    }
alpar@1253
    75
    ///Remove a fix id.
alpar@1253
    76
alpar@1253
    77
    ///\param n is a fix id
alpar@1253
    78
    ///
alpar@1253
    79
    void erase(int n) 
alpar@1253
    80
    {
alpar@1253
    81
      int fl=index[n];
alpar@1253
    82
      index[n]=first_free;
alpar@1253
    83
      first_free=n;
alpar@1253
    84
      for(int i=fl+1;i<int(cross.size());++i) {
alpar@1253
    85
	cross[i-1]=cross[i];
alpar@1253
    86
	index[cross[i]]--;
alpar@1253
    87
      }
alpar@1253
    88
      cross.pop_back();
alpar@1253
    89
    }
alpar@1253
    90
    ///An upper bound on the largest fix id.
alpar@1253
    91
alpar@1253
    92
    ///\todo Do we need this?
alpar@1253
    93
    ///
alpar@1253
    94
    std::size_t maxFixId() { return cross.size()-1; }
alpar@1253
    95
  
alpar@1253
    96
  };
alpar@1253
    97
    
alpar@1253
    98
  ///Common base class for LP solvers
athos@1246
    99
  class LpSolverBase {
alpar@1253
   100
    
athos@1247
   101
  public:
athos@1247
   102
alpar@1263
   103
    ///\e
alpar@1263
   104
    enum SolutionType {
alpar@1263
   105
      ///\e
alpar@1263
   106
      INFEASIBLE = 0,
alpar@1263
   107
      ///\e
alpar@1263
   108
      UNBOUNDED = 1,
alpar@1263
   109
      ///\e
alpar@1263
   110
      OPTIMAL = 2,
alpar@1263
   111
      ///\e
alpar@1263
   112
      FEASIBLE = 3,
alpar@1263
   113
    };
alpar@1263
   114
      
alpar@1256
   115
    ///The floating point type used by the solver
athos@1247
   116
    typedef double Value;
alpar@1256
   117
    ///The infinity constant
athos@1247
   118
    static const Value INF;
alpar@1264
   119
    ///The not a number constant
alpar@1264
   120
    static const Value NaN;
alpar@1253
   121
    
alpar@1256
   122
    ///Refer to a column of the LP.
alpar@1256
   123
alpar@1256
   124
    ///This type is used to refer to a column of the LP.
alpar@1256
   125
    ///
alpar@1256
   126
    ///Its value remains valid and correct even after the addition or erase of
alpar@1256
   127
    ///new column (unless the referred column itself was also deleted,
alpar@1256
   128
    ///of course).
alpar@1256
   129
    ///
alpar@1256
   130
    ///\todo Document what can one do with a Col (INVALID, comparing,
alpar@1256
   131
    ///it is similar to Node/Edge)
alpar@1256
   132
    class Col {
alpar@1256
   133
    protected:
alpar@1256
   134
      int id;
alpar@1256
   135
      friend class LpSolverBase;
alpar@1256
   136
    public:
alpar@1259
   137
      typedef Value ExprValue;
alpar@1256
   138
      typedef True LpSolverCol;
alpar@1256
   139
      Col() {}
alpar@1256
   140
      Col(const Invalid&) : id(-1) {}
alpar@1256
   141
      bool operator<(Col c) const  {return id<c.id;}
alpar@1256
   142
      bool operator==(Col c) const  {return id==c.id;}
alpar@1256
   143
      bool operator!=(Col c) const  {return id==c.id;}
alpar@1256
   144
    };
alpar@1256
   145
alpar@1256
   146
    ///Refer to a row of the LP.
alpar@1256
   147
alpar@1256
   148
    ///This type is used to refer to a row of the LP.
alpar@1256
   149
    ///
alpar@1256
   150
    ///Its value remains valid and correct even after the addition or erase of
alpar@1256
   151
    ///new rows (unless the referred row itself was also deleted, of course).
alpar@1256
   152
    ///
alpar@1256
   153
    ///\todo Document what can one do with a Row (INVALID, comparing,
alpar@1256
   154
    ///it is similar to Node/Edge)
alpar@1256
   155
    class Row {
alpar@1256
   156
    protected:
alpar@1256
   157
      int id;
alpar@1256
   158
      friend class LpSolverBase;
alpar@1256
   159
    public:
alpar@1259
   160
      typedef Value ExprValue;
alpar@1256
   161
      typedef True LpSolverRow;
alpar@1256
   162
      Row() {}
alpar@1256
   163
      Row(const Invalid&) : id(-1) {}
alpar@1256
   164
      typedef True LpSolverRow;
alpar@1256
   165
      bool operator<(Row c) const  {return id<c.id;}
alpar@1256
   166
      bool operator==(Row c) const  {return id==c.id;}
alpar@1256
   167
      bool operator!=(Row c) const  {return id==c.id;} 
alpar@1256
   168
   };
alpar@1259
   169
    
alpar@1259
   170
    ///Linear expression
alpar@1259
   171
    typedef SparseLinExpr<Col> Expr;
alpar@1264
   172
    ///Linear constraint
alpar@1264
   173
    typedef LinConstr<Expr> Constr;
alpar@1253
   174
alpar@1253
   175
  protected:
alpar@1253
   176
    _FixId rows;
alpar@1253
   177
    _FixId cols;
athos@1246
   178
athos@1246
   179
    /// \e
athos@1246
   180
    virtual int _addCol() = 0;
athos@1246
   181
    /// \e
athos@1246
   182
    virtual int _addRow() = 0;
athos@1246
   183
    /// \e
alpar@1253
   184
athos@1246
   185
    /// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
alpar@1253
   186
    ///
athos@1246
   187
    virtual void _setRowCoeffs(int i, 
athos@1251
   188
			       int length,
athos@1247
   189
                               int  const * indices, 
athos@1247
   190
                               Value  const * values ) = 0;
athos@1246
   191
    /// \e
alpar@1253
   192
athos@1246
   193
    /// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
alpar@1253
   194
    ///
athos@1246
   195
    virtual void _setColCoeffs(int i, 
athos@1251
   196
			       int length,
athos@1247
   197
                               int  const * indices, 
athos@1247
   198
                               Value  const * values ) = 0;
athos@1246
   199
    
athos@1247
   200
    /// \e
alpar@1253
   201
athos@1247
   202
    /// The lower bound of a variable (column) have to be given by an 
athos@1247
   203
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   204
    /// Value or -\ref INF.
athos@1247
   205
    virtual void _setColLowerBound(int i, Value value) = 0;
athos@1247
   206
    /// \e
alpar@1253
   207
athos@1247
   208
    /// The upper bound of a variable (column) have to be given by an 
athos@1247
   209
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   210
    /// Value or \ref INF.
athos@1247
   211
    virtual void _setColUpperBound(int i, Value value) = 0;
athos@1247
   212
    /// \e
alpar@1253
   213
athos@1247
   214
    /// The lower bound of a linear expression (row) have to be given by an 
athos@1247
   215
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   216
    /// Value or -\ref INF.
athos@1247
   217
    virtual void _setRowLowerBound(int i, Value value) = 0;
athos@1247
   218
    /// \e
alpar@1253
   219
athos@1247
   220
    /// The upper bound of a linear expression (row) have to be given by an 
athos@1247
   221
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   222
    /// Value or \ref INF.
athos@1247
   223
    virtual void _setRowUpperBound(int i, Value value) = 0;
athos@1247
   224
athos@1247
   225
    /// \e
athos@1247
   226
    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
alpar@1253
   227
alpar@1253
   228
    ///\e
alpar@1263
   229
    
alpar@1263
   230
    ///\bug Wrong interface
alpar@1263
   231
    ///
alpar@1263
   232
    virtual SolutionType _solve() = 0;
alpar@1263
   233
alpar@1263
   234
    ///\e
alpar@1263
   235
alpar@1263
   236
    ///\bug Wrong interface
alpar@1263
   237
    ///
alpar@1263
   238
    virtual Value _getSolution(int i) = 0;
alpar@1263
   239
    ///\e
alpar@1253
   240
alpar@1253
   241
    ///\bug unimplemented!!!!
alpar@1253
   242
    void clearObj() {}
alpar@1253
   243
  public:
alpar@1253
   244
alpar@1253
   245
alpar@1253
   246
    ///\e
alpar@1253
   247
    virtual ~LpSolverBase() {}
alpar@1253
   248
alpar@1263
   249
    ///\name Building up and modification of the LP
alpar@1263
   250
alpar@1263
   251
    ///@{
alpar@1263
   252
alpar@1253
   253
    ///Add a new empty column (i.e a new variable) to the LP
alpar@1253
   254
    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
alpar@1263
   255
alpar@1256
   256
    ///\brief Fill the elements of a container with newly created columns
alpar@1256
   257
    ///(i.e a new variables)
alpar@1256
   258
    ///
alpar@1256
   259
    ///This magic function takes container as its argument
alpar@1256
   260
    ///and fills its elements
alpar@1256
   261
    ///with new columns (i.e. variables)
alpar@1256
   262
    ///\param t can be either any standard STL iterable container with
alpar@1256
   263
    ///\ref Col \c values_type or \c mapped_type
alpar@1256
   264
    ///like <tt>std::vector<LpSolverBase::Col></tt>,
alpar@1256
   265
    /// <tt>std::list<LpSolverBase::Col></tt> or
alpar@1256
   266
    /// <tt>std::map<AnyType,LpSolverBase::Col></tt> or
alpar@1256
   267
    ///it can be an iterable lemon map like 
alpar@1256
   268
    /// <tt>ListGraph::NodeMap<LpSolverBase::Col></tt>.
alpar@1256
   269
    ///\return The number of the created column.
alpar@1256
   270
    ///\bug Iterable nodemap hasn't been implemented yet.
alpar@1256
   271
#ifdef DOXYGEN
alpar@1256
   272
    template<class T>
alpar@1256
   273
    int addColSet(T &t) { return 0;} 
alpar@1256
   274
#else
alpar@1256
   275
    template<class T>
alpar@1256
   276
    typename enable_if<typename T::value_type::LpSolverCol,int>::type
alpar@1256
   277
    addColSet(T &t,dummy<0> = 0) {
alpar@1256
   278
      int s=0;
alpar@1256
   279
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
alpar@1256
   280
      return s;
alpar@1256
   281
    }
alpar@1256
   282
    template<class T>
alpar@1256
   283
    typename enable_if<typename T::value_type::second_type::LpSolverCol,
alpar@1256
   284
		       int>::type
alpar@1256
   285
    addColSet(T &t,dummy<1> = 1) { 
alpar@1256
   286
      int s=0;
alpar@1256
   287
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
alpar@1256
   288
	i->second=addCol();
alpar@1256
   289
	s++;
alpar@1256
   290
      }
alpar@1256
   291
      return s;
alpar@1256
   292
    }
alpar@1256
   293
#endif
alpar@1263
   294
alpar@1253
   295
    ///Add a new empty row (i.e a new constaint) to the LP
alpar@1258
   296
alpar@1258
   297
    ///This function adds a new empty row (i.e a new constaint) to the LP.
alpar@1258
   298
    ///\return The created row
alpar@1253
   299
    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
alpar@1253
   300
alpar@1258
   301
    ///Set a row (i.e a constaint) of the LP
alpar@1253
   302
alpar@1258
   303
    ///\param r is the row to be modified
alpar@1259
   304
    ///\param l is lower bound (-\ref INF means no bound)
alpar@1258
   305
    ///\param e is a linear expression (see \ref Expr)
alpar@1259
   306
    ///\param u is the upper bound (\ref INF means no bound)
alpar@1253
   307
    ///\bug This is a temportary function. The interface will change to
alpar@1253
   308
    ///a better one.
alpar@1258
   309
    void setRow(Row r, Value l,const Expr &e, Value u) {
alpar@1253
   310
      std::vector<int> indices;
alpar@1253
   311
      std::vector<Value> values;
alpar@1253
   312
      indices.push_back(0);
alpar@1253
   313
      values.push_back(0);
alpar@1258
   314
      for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
alpar@1256
   315
	if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
alpar@1256
   316
	  indices.push_back(cols.floatingId((*i).first.id));
alpar@1256
   317
	  values.push_back((*i).second);
alpar@1256
   318
	}
alpar@1253
   319
      _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
alpar@1253
   320
		    &indices[0],&values[0]);
alpar@1256
   321
      _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
alpar@1256
   322
      _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
alpar@1258
   323
    }
alpar@1258
   324
alpar@1264
   325
    ///Set a row (i.e a constaint) of the LP
alpar@1264
   326
alpar@1264
   327
    ///\param r is the row to be modified
alpar@1264
   328
    ///\param c is a linear expression (see \ref Constr)
alpar@1264
   329
    ///\bug This is a temportary function. The interface will change to
alpar@1264
   330
    ///a better one.
alpar@1264
   331
    void setRow(Row r, const Constr &c) {
alpar@1264
   332
      Value lb= c.lb==NaN?-INF:lb;
alpar@1264
   333
      Value ub= c.ub==NaN?INF:lb;
alpar@1264
   334
      setRow(r,lb,c.expr,ub);
alpar@1264
   335
    }
alpar@1264
   336
alpar@1258
   337
    ///Add a new row (i.e a new constaint) to the LP
alpar@1258
   338
alpar@1259
   339
    ///\param l is the lower bound (-\ref INF means no bound)
alpar@1258
   340
    ///\param e is a linear expression (see \ref Expr)
alpar@1259
   341
    ///\param u is the upper bound (\ref INF means no bound)
alpar@1258
   342
    ///\return The created row.
alpar@1258
   343
    ///\bug This is a temportary function. The interface will change to
alpar@1258
   344
    ///a better one.
alpar@1258
   345
    Row addRow(Value l,const Expr &e, Value u) {
alpar@1258
   346
      Row r=addRow();
alpar@1258
   347
      setRow(r,l,e,u);
alpar@1253
   348
      return r;
alpar@1253
   349
    }
alpar@1253
   350
alpar@1264
   351
    ///Add a new row (i.e a new constaint) to the LP
alpar@1264
   352
alpar@1264
   353
    ///\param c is a linear expression (see \ref Constr)
alpar@1264
   354
    ///\return The created row.
alpar@1264
   355
    ///\bug This is a temportary function. The interface will change to
alpar@1264
   356
    ///a better one.
alpar@1264
   357
    Row addRow(const Constr &c) {
alpar@1264
   358
      Row r=addRow();
alpar@1264
   359
      setRow(r,c);
alpar@1264
   360
      return r;
alpar@1264
   361
    }
alpar@1264
   362
alpar@1253
   363
    /// Set the lower bound of a column (i.e a variable)
alpar@1253
   364
alpar@1253
   365
    /// The upper bound of a variable (column) have to be given by an 
alpar@1253
   366
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   367
    /// Value or -\ref INF.
alpar@1253
   368
    virtual void setColLowerBound(Col c, Value value) {
alpar@1253
   369
      _setColLowerBound(cols.floatingId(c.id),value);
alpar@1253
   370
    }
alpar@1253
   371
    /// Set the upper bound of a column (i.e a variable)
alpar@1253
   372
alpar@1253
   373
    /// The upper bound of a variable (column) have to be given by an 
alpar@1253
   374
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   375
    /// Value or \ref INF.
alpar@1253
   376
    virtual void setColUpperBound(Col c, Value value) {
alpar@1253
   377
      _setColUpperBound(cols.floatingId(c.id),value);
alpar@1253
   378
    };
alpar@1253
   379
    /// Set the lower bound of a row (i.e a constraint)
alpar@1253
   380
alpar@1253
   381
    /// The lower bound of a linear expression (row) have to be given by an 
alpar@1253
   382
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   383
    /// Value or -\ref INF.
alpar@1253
   384
    virtual void setRowLowerBound(Row r, Value value) {
alpar@1253
   385
      _setRowLowerBound(rows.floatingId(r.id),value);
alpar@1253
   386
    };
alpar@1253
   387
    /// Set the upper bound of a row (i.e a constraint)
alpar@1253
   388
alpar@1253
   389
    /// The upper bound of a linear expression (row) have to be given by an 
alpar@1253
   390
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   391
    /// Value or \ref INF.
alpar@1253
   392
    virtual void setRowUpperBound(Row r, Value value) {
alpar@1253
   393
      _setRowUpperBound(rows.floatingId(r.id),value);
alpar@1253
   394
    };
alpar@1253
   395
    ///Set an element of the objective function
alpar@1253
   396
    void setObjCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
alpar@1253
   397
    ///Set the objective function
alpar@1253
   398
    
alpar@1253
   399
    ///\param e is a linear expression of type \ref Expr.
alpar@1253
   400
    ///\todo What to do with the constant component?
alpar@1253
   401
    void setObj(Expr e) {
alpar@1253
   402
      clearObj();
alpar@1253
   403
      for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
alpar@1253
   404
	setObjCoeff((*i).first,(*i).second);
alpar@1253
   405
    }
alpar@1263
   406
alpar@1263
   407
    ///@}
alpar@1263
   408
alpar@1263
   409
alpar@1263
   410
    ///\name Solving the LP
alpar@1263
   411
alpar@1263
   412
    ///@{
alpar@1263
   413
alpar@1263
   414
    ///\e
alpar@1263
   415
    SolutionType solve() { return _solve(); }
alpar@1263
   416
    
alpar@1263
   417
    ///@}
alpar@1263
   418
    
alpar@1263
   419
    ///\name Obtaining the solution LP
alpar@1263
   420
alpar@1263
   421
    ///@{
alpar@1263
   422
alpar@1263
   423
    ///\e
alpar@1263
   424
    Value solution(Col c) { return _getSolution(cols.floatingId(c.id)); }
alpar@1263
   425
alpar@1263
   426
    ///@}
alpar@1253
   427
    
athos@1248
   428
  };  
athos@1246
   429
athos@1246
   430
} //namespace lemon
athos@1246
   431
athos@1246
   432
#endif //LEMON_LP_BASE_H