src/work/athos/lp/lp_base.h
author alpar
Fri, 25 Mar 2005 16:19:03 +0000
changeset 1263 a490938ad0aa
parent 1259 11a09f1319b3
child 1264 92ba3e62825d
permissions -rw-r--r--
- LpGlpk added to the makefile
- missing const_cast<>() added
- prop for two new functions (solve() and solution())
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@1253
   119
    
alpar@1256
   120
    ///Refer to a column of the LP.
alpar@1256
   121
alpar@1256
   122
    ///This type is used to refer to a column of the LP.
alpar@1256
   123
    ///
alpar@1256
   124
    ///Its value remains valid and correct even after the addition or erase of
alpar@1256
   125
    ///new column (unless the referred column itself was also deleted,
alpar@1256
   126
    ///of course).
alpar@1256
   127
    ///
alpar@1256
   128
    ///\todo Document what can one do with a Col (INVALID, comparing,
alpar@1256
   129
    ///it is similar to Node/Edge)
alpar@1256
   130
    class Col {
alpar@1256
   131
    protected:
alpar@1256
   132
      int id;
alpar@1256
   133
      friend class LpSolverBase;
alpar@1256
   134
    public:
alpar@1259
   135
      typedef Value ExprValue;
alpar@1256
   136
      typedef True LpSolverCol;
alpar@1256
   137
      Col() {}
alpar@1256
   138
      Col(const Invalid&) : id(-1) {}
alpar@1256
   139
      bool operator<(Col c) const  {return id<c.id;}
alpar@1256
   140
      bool operator==(Col c) const  {return id==c.id;}
alpar@1256
   141
      bool operator!=(Col c) const  {return id==c.id;}
alpar@1256
   142
    };
alpar@1256
   143
alpar@1256
   144
    ///Refer to a row of the LP.
alpar@1256
   145
alpar@1256
   146
    ///This type is used to refer to a row of the LP.
alpar@1256
   147
    ///
alpar@1256
   148
    ///Its value remains valid and correct even after the addition or erase of
alpar@1256
   149
    ///new rows (unless the referred row itself was also deleted, of course).
alpar@1256
   150
    ///
alpar@1256
   151
    ///\todo Document what can one do with a Row (INVALID, comparing,
alpar@1256
   152
    ///it is similar to Node/Edge)
alpar@1256
   153
    class Row {
alpar@1256
   154
    protected:
alpar@1256
   155
      int id;
alpar@1256
   156
      friend class LpSolverBase;
alpar@1256
   157
    public:
alpar@1259
   158
      typedef Value ExprValue;
alpar@1256
   159
      typedef True LpSolverRow;
alpar@1256
   160
      Row() {}
alpar@1256
   161
      Row(const Invalid&) : id(-1) {}
alpar@1256
   162
      typedef True LpSolverRow;
alpar@1256
   163
      bool operator<(Row c) const  {return id<c.id;}
alpar@1256
   164
      bool operator==(Row c) const  {return id==c.id;}
alpar@1256
   165
      bool operator!=(Row c) const  {return id==c.id;} 
alpar@1256
   166
   };
alpar@1259
   167
    
alpar@1259
   168
    ///Linear expression
alpar@1259
   169
    typedef SparseLinExpr<Col> Expr;
alpar@1253
   170
alpar@1253
   171
  protected:
alpar@1253
   172
    _FixId rows;
alpar@1253
   173
    _FixId cols;
athos@1246
   174
athos@1246
   175
    /// \e
athos@1246
   176
    virtual int _addCol() = 0;
athos@1246
   177
    /// \e
athos@1246
   178
    virtual int _addRow() = 0;
athos@1246
   179
    /// \e
alpar@1253
   180
athos@1246
   181
    /// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
alpar@1253
   182
    ///
athos@1246
   183
    virtual void _setRowCoeffs(int i, 
athos@1251
   184
			       int length,
athos@1247
   185
                               int  const * indices, 
athos@1247
   186
                               Value  const * values ) = 0;
athos@1246
   187
    /// \e
alpar@1253
   188
athos@1246
   189
    /// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
alpar@1253
   190
    ///
athos@1246
   191
    virtual void _setColCoeffs(int i, 
athos@1251
   192
			       int length,
athos@1247
   193
                               int  const * indices, 
athos@1247
   194
                               Value  const * values ) = 0;
athos@1246
   195
    
athos@1247
   196
    /// \e
alpar@1253
   197
athos@1247
   198
    /// The lower bound of a variable (column) have to be given by an 
athos@1247
   199
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   200
    /// Value or -\ref INF.
athos@1247
   201
    virtual void _setColLowerBound(int i, Value value) = 0;
athos@1247
   202
    /// \e
alpar@1253
   203
athos@1247
   204
    /// The upper bound of a variable (column) have to be given by an 
athos@1247
   205
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   206
    /// Value or \ref INF.
athos@1247
   207
    virtual void _setColUpperBound(int i, Value value) = 0;
athos@1247
   208
    /// \e
alpar@1253
   209
athos@1247
   210
    /// The lower bound of a linear expression (row) have to be given by an 
athos@1247
   211
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   212
    /// Value or -\ref INF.
athos@1247
   213
    virtual void _setRowLowerBound(int i, Value value) = 0;
athos@1247
   214
    /// \e
alpar@1253
   215
athos@1247
   216
    /// The upper bound of a linear expression (row) have to be given by an 
athos@1247
   217
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   218
    /// Value or \ref INF.
athos@1247
   219
    virtual void _setRowUpperBound(int i, Value value) = 0;
athos@1247
   220
athos@1247
   221
    /// \e
athos@1247
   222
    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
alpar@1253
   223
alpar@1253
   224
    ///\e
alpar@1263
   225
    
alpar@1263
   226
    ///\bug Wrong interface
alpar@1263
   227
    ///
alpar@1263
   228
    virtual SolutionType _solve() = 0;
alpar@1263
   229
alpar@1263
   230
    ///\e
alpar@1263
   231
alpar@1263
   232
    ///\bug Wrong interface
alpar@1263
   233
    ///
alpar@1263
   234
    virtual Value _getSolution(int i) = 0;
alpar@1263
   235
    ///\e
alpar@1253
   236
alpar@1253
   237
    ///\bug unimplemented!!!!
alpar@1253
   238
    void clearObj() {}
alpar@1253
   239
  public:
alpar@1253
   240
alpar@1253
   241
alpar@1253
   242
    ///\e
alpar@1253
   243
    virtual ~LpSolverBase() {}
alpar@1253
   244
alpar@1263
   245
    ///\name Building up and modification of the LP
alpar@1263
   246
alpar@1263
   247
    ///@{
alpar@1263
   248
alpar@1253
   249
    ///Add a new empty column (i.e a new variable) to the LP
alpar@1253
   250
    Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
alpar@1263
   251
alpar@1256
   252
    ///\brief Fill the elements of a container with newly created columns
alpar@1256
   253
    ///(i.e a new variables)
alpar@1256
   254
    ///
alpar@1256
   255
    ///This magic function takes container as its argument
alpar@1256
   256
    ///and fills its elements
alpar@1256
   257
    ///with new columns (i.e. variables)
alpar@1256
   258
    ///\param t can be either any standard STL iterable container with
alpar@1256
   259
    ///\ref Col \c values_type or \c mapped_type
alpar@1256
   260
    ///like <tt>std::vector<LpSolverBase::Col></tt>,
alpar@1256
   261
    /// <tt>std::list<LpSolverBase::Col></tt> or
alpar@1256
   262
    /// <tt>std::map<AnyType,LpSolverBase::Col></tt> or
alpar@1256
   263
    ///it can be an iterable lemon map like 
alpar@1256
   264
    /// <tt>ListGraph::NodeMap<LpSolverBase::Col></tt>.
alpar@1256
   265
    ///\return The number of the created column.
alpar@1256
   266
    ///\bug Iterable nodemap hasn't been implemented yet.
alpar@1256
   267
#ifdef DOXYGEN
alpar@1256
   268
    template<class T>
alpar@1256
   269
    int addColSet(T &t) { return 0;} 
alpar@1256
   270
#else
alpar@1256
   271
    template<class T>
alpar@1256
   272
    typename enable_if<typename T::value_type::LpSolverCol,int>::type
alpar@1256
   273
    addColSet(T &t,dummy<0> = 0) {
alpar@1256
   274
      int s=0;
alpar@1256
   275
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
alpar@1256
   276
      return s;
alpar@1256
   277
    }
alpar@1256
   278
    template<class T>
alpar@1256
   279
    typename enable_if<typename T::value_type::second_type::LpSolverCol,
alpar@1256
   280
		       int>::type
alpar@1256
   281
    addColSet(T &t,dummy<1> = 1) { 
alpar@1256
   282
      int s=0;
alpar@1256
   283
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
alpar@1256
   284
	i->second=addCol();
alpar@1256
   285
	s++;
alpar@1256
   286
      }
alpar@1256
   287
      return s;
alpar@1256
   288
    }
alpar@1256
   289
#endif
alpar@1263
   290
alpar@1253
   291
    ///Add a new empty row (i.e a new constaint) to the LP
alpar@1258
   292
alpar@1258
   293
    ///This function adds a new empty row (i.e a new constaint) to the LP.
alpar@1258
   294
    ///\return The created row
alpar@1253
   295
    Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
alpar@1253
   296
alpar@1258
   297
    ///Set a row (i.e a constaint) of the LP
alpar@1253
   298
alpar@1258
   299
    ///\param r is the row to be modified
alpar@1259
   300
    ///\param l is lower bound (-\ref INF means no bound)
alpar@1258
   301
    ///\param e is a linear expression (see \ref Expr)
alpar@1259
   302
    ///\param u is the upper bound (\ref INF means no bound)
alpar@1253
   303
    ///\bug This is a temportary function. The interface will change to
alpar@1253
   304
    ///a better one.
alpar@1258
   305
    void setRow(Row r, Value l,const Expr &e, Value u) {
alpar@1253
   306
      std::vector<int> indices;
alpar@1253
   307
      std::vector<Value> values;
alpar@1253
   308
      indices.push_back(0);
alpar@1253
   309
      values.push_back(0);
alpar@1258
   310
      for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i)
alpar@1256
   311
	if((*i).second!=0) { ///\bug EPSILON would be necessary here!!!
alpar@1256
   312
	  indices.push_back(cols.floatingId((*i).first.id));
alpar@1256
   313
	  values.push_back((*i).second);
alpar@1256
   314
	}
alpar@1253
   315
      _setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
alpar@1253
   316
		    &indices[0],&values[0]);
alpar@1256
   317
      _setRowLowerBound(rows.floatingId(r.id),l-e.constComp());
alpar@1256
   318
      _setRowUpperBound(rows.floatingId(r.id),u-e.constComp());
alpar@1258
   319
    }
alpar@1258
   320
alpar@1258
   321
    ///Add a new row (i.e a new constaint) to the LP
alpar@1258
   322
alpar@1259
   323
    ///\param l is the lower bound (-\ref INF means no bound)
alpar@1258
   324
    ///\param e is a linear expression (see \ref Expr)
alpar@1259
   325
    ///\param u is the upper bound (\ref INF means no bound)
alpar@1258
   326
    ///\return The created row.
alpar@1258
   327
    ///\bug This is a temportary function. The interface will change to
alpar@1258
   328
    ///a better one.
alpar@1258
   329
    Row addRow(Value l,const Expr &e, Value u) {
alpar@1258
   330
      Row r=addRow();
alpar@1258
   331
      setRow(r,l,e,u);
alpar@1253
   332
      return r;
alpar@1253
   333
    }
alpar@1253
   334
alpar@1253
   335
    /// Set the lower bound of a column (i.e a variable)
alpar@1253
   336
alpar@1253
   337
    /// The upper bound of a variable (column) have to be given by an 
alpar@1253
   338
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   339
    /// Value or -\ref INF.
alpar@1253
   340
    virtual void setColLowerBound(Col c, Value value) {
alpar@1253
   341
      _setColLowerBound(cols.floatingId(c.id),value);
alpar@1253
   342
    }
alpar@1253
   343
    /// Set the upper bound of a column (i.e a variable)
alpar@1253
   344
alpar@1253
   345
    /// The upper bound of a variable (column) have to be given by an 
alpar@1253
   346
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   347
    /// Value or \ref INF.
alpar@1253
   348
    virtual void setColUpperBound(Col c, Value value) {
alpar@1253
   349
      _setColUpperBound(cols.floatingId(c.id),value);
alpar@1253
   350
    };
alpar@1253
   351
    /// Set the lower bound of a row (i.e a constraint)
alpar@1253
   352
alpar@1253
   353
    /// The lower bound of a linear expression (row) have to be given by an 
alpar@1253
   354
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   355
    /// Value or -\ref INF.
alpar@1253
   356
    virtual void setRowLowerBound(Row r, Value value) {
alpar@1253
   357
      _setRowLowerBound(rows.floatingId(r.id),value);
alpar@1253
   358
    };
alpar@1253
   359
    /// Set the upper bound of a row (i.e a constraint)
alpar@1253
   360
alpar@1253
   361
    /// The upper bound of a linear expression (row) have to be given by an 
alpar@1253
   362
    /// extended number of type Value, i.e. a finite number of type 
alpar@1259
   363
    /// Value or \ref INF.
alpar@1253
   364
    virtual void setRowUpperBound(Row r, Value value) {
alpar@1253
   365
      _setRowUpperBound(rows.floatingId(r.id),value);
alpar@1253
   366
    };
alpar@1253
   367
    ///Set an element of the objective function
alpar@1253
   368
    void setObjCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
alpar@1253
   369
    ///Set the objective function
alpar@1253
   370
    
alpar@1253
   371
    ///\param e is a linear expression of type \ref Expr.
alpar@1253
   372
    ///\todo What to do with the constant component?
alpar@1253
   373
    void setObj(Expr e) {
alpar@1253
   374
      clearObj();
alpar@1253
   375
      for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
alpar@1253
   376
	setObjCoeff((*i).first,(*i).second);
alpar@1253
   377
    }
alpar@1263
   378
alpar@1263
   379
    ///@}
alpar@1263
   380
alpar@1263
   381
alpar@1263
   382
    ///\name Solving the LP
alpar@1263
   383
alpar@1263
   384
    ///@{
alpar@1263
   385
alpar@1263
   386
    ///\e
alpar@1263
   387
    SolutionType solve() { return _solve(); }
alpar@1263
   388
    
alpar@1263
   389
    ///@}
alpar@1263
   390
    
alpar@1263
   391
    ///\name Obtaining the solution LP
alpar@1263
   392
alpar@1263
   393
    ///@{
alpar@1263
   394
alpar@1263
   395
    ///\e
alpar@1263
   396
    Value solution(Col c) { return _getSolution(cols.floatingId(c.id)); }
alpar@1263
   397
alpar@1263
   398
    ///@}
alpar@1253
   399
    
athos@1248
   400
  };  
athos@1246
   401
athos@1246
   402
} //namespace lemon
athos@1246
   403
athos@1246
   404
#endif //LEMON_LP_BASE_H