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