src/work/marci/lp/lp_solver_base.h
author alpar
Mon, 28 Feb 2005 13:03:36 +0000
changeset 1180 f772c360b466
parent 1152 1765ff9fefa1
child 1262 61f989e3e525
permissions -rw-r--r--
Better color to bw conversion
marci@1031
     1
// -*- c++ -*-
marci@1152
     2
#ifndef LEMON_LP_SOLVER_BASE_H
marci@1152
     3
#define LEMON_LP_SOLVER_BASE_H
marci@1031
     4
marci@1031
     5
///\ingroup misc
marci@1031
     6
///\file
marci@1031
     7
marci@1031
     8
// #include <stdio.h>
marci@1031
     9
#include <stdlib.h>
marci@1097
    10
#include <iostream>
marci@1097
    11
#include <map>
marci@1104
    12
#include <limits>
marci@1031
    13
// #include <stdio>
marci@1031
    14
//#include <stdlib>
marci@1031
    15
extern "C" {
marci@1031
    16
#include "glpk.h"
marci@1031
    17
}
marci@1031
    18
marci@1031
    19
#include <iostream>
marci@1031
    20
#include <vector>
marci@1031
    21
#include <string>
marci@1031
    22
#include <list>
marci@1031
    23
#include <memory>
marci@1031
    24
#include <utility>
marci@1031
    25
marci@1031
    26
#include <lemon/invalid.h>
marci@1099
    27
#include <expression.h>
marci@1031
    28
//#include <stp.h>
marci@1031
    29
//#include <lemon/max_flow.h>
marci@1031
    30
//#include <augmenting_flow.h>
marci@1031
    31
//#include <iter_map.h>
marci@1031
    32
marci@1031
    33
using std::cout;
marci@1031
    34
using std::cin;
marci@1031
    35
using std::endl;
marci@1031
    36
marci@1031
    37
namespace lemon {
marci@1031
    38
  
marci@1031
    39
  /// \addtogroup misc
marci@1031
    40
  /// @{
marci@1031
    41
marci@1031
    42
  /// \brief A partitioned vector with iterable classes.
marci@1031
    43
  ///
marci@1031
    44
  /// This class implements a container in which the data is stored in an 
marci@1031
    45
  /// stl vector, the range is partitioned into sets and each set is 
marci@1031
    46
  /// doubly linked in a list. 
marci@1031
    47
  /// That is, each class is iterable by lemon iterators, and any member of 
marci@1031
    48
  /// the vector can bo moved to an other class.
marci@1031
    49
  template <typename T>
marci@1031
    50
  class IterablePartition {
marci@1031
    51
  protected:
marci@1031
    52
    struct Node {
marci@1031
    53
      T data;
marci@1031
    54
      int prev; //invalid az -1
marci@1031
    55
      int next; 
marci@1031
    56
    };
marci@1031
    57
    std::vector<Node> nodes;
marci@1031
    58
    struct Tip {
marci@1031
    59
      int first;
marci@1031
    60
      int last;
marci@1031
    61
    };
marci@1031
    62
    std::vector<Tip> tips;
marci@1031
    63
  public:
marci@1031
    64
    /// The classes are indexed by integers from \c 0 to \c classNum()-1.
marci@1031
    65
    int classNum() const { return tips.size(); }
marci@1031
    66
    /// This lemon style iterator iterates through a class. 
marci@1152
    67
    class Class;
marci@1031
    68
    /// Constructor. The number of classes is to be given which is fixed 
marci@1031
    69
    /// over the life of the container. 
marci@1031
    70
    /// The partition classes are indexed from 0 to class_num-1. 
marci@1031
    71
    IterablePartition(int class_num) { 
marci@1031
    72
      for (int i=0; i<class_num; ++i) {
marci@1031
    73
	Tip t;
marci@1031
    74
	t.first=t.last=-1;
marci@1031
    75
	tips.push_back(t);
marci@1031
    76
      }
marci@1031
    77
    }
marci@1031
    78
  protected:
marci@1152
    79
    void befuz(Class it, int class_id) {
marci@1031
    80
      if (tips[class_id].first==-1) {
marci@1031
    81
	if (tips[class_id].last==-1) {
marci@1031
    82
	  nodes[it.i].prev=nodes[it.i].next=-1;
marci@1031
    83
	  tips[class_id].first=tips[class_id].last=it.i;
marci@1031
    84
	}
marci@1031
    85
      } else {
marci@1031
    86
	nodes[it.i].prev=tips[class_id].last;
marci@1031
    87
	nodes[it.i].next=-1;
marci@1031
    88
	nodes[tips[class_id].last].next=it.i;
marci@1031
    89
	tips[class_id].last=it.i;
marci@1031
    90
      }
marci@1031
    91
    }
marci@1152
    92
    void kifuz(Class it, int class_id) {
marci@1031
    93
      if (tips[class_id].first==it.i) {
marci@1031
    94
	if (tips[class_id].last==it.i) {
marci@1031
    95
	  tips[class_id].first=tips[class_id].last=-1;
marci@1031
    96
	} else {
marci@1031
    97
	  tips[class_id].first=nodes[it.i].next;
marci@1031
    98
	  nodes[nodes[it.i].next].prev=-1;
marci@1031
    99
	}
marci@1031
   100
      } else {
marci@1031
   101
	if (tips[class_id].last==it.i) {
marci@1031
   102
	  tips[class_id].last=nodes[it.i].prev;
marci@1031
   103
	  nodes[nodes[it.i].prev].next=-1;
marci@1031
   104
	} else {
marci@1031
   105
	  nodes[nodes[it.i].next].prev=nodes[it.i].prev;
marci@1031
   106
	  nodes[nodes[it.i].prev].next=nodes[it.i].next;
marci@1031
   107
	}
marci@1031
   108
      }
marci@1031
   109
    }
marci@1031
   110
  public:
marci@1031
   111
    /// A new element with data \c t is pushed into the vector and into class 
marci@1031
   112
    /// \c class_id.
marci@1152
   113
    Class push_back(const T& t, int class_id) { 
marci@1031
   114
      Node n;
marci@1031
   115
      n.data=t;
marci@1031
   116
      nodes.push_back(n);
marci@1031
   117
      int i=nodes.size()-1;
marci@1031
   118
      befuz(i, class_id);
marci@1031
   119
      return i;
marci@1031
   120
    }
marci@1031
   121
    /// A member is moved to an other class.
marci@1152
   122
    void set(Class it, int old_class_id, int new_class_id) {
marci@1031
   123
      kifuz(it.i, old_class_id);
marci@1031
   124
      befuz(it.i, new_class_id);
marci@1031
   125
    }
marci@1031
   126
    /// Returns the data pointed by \c it.
marci@1152
   127
    T& operator[](Class it) { return nodes[it.i].data; }
marci@1031
   128
    /// Returns the data pointed by \c it.
marci@1152
   129
    const T& operator[](Class it) const { return nodes[it.i].data; }
marci@1031
   130
    ///.
marci@1152
   131
    class Class {
marci@1031
   132
      friend class IterablePartition;
marci@1031
   133
    protected:
marci@1031
   134
      int i;
marci@1031
   135
    public:
marci@1031
   136
      /// Default constructor.
marci@1152
   137
      Class() { }
marci@1031
   138
      /// This constructor constructs an iterator which points
marci@1031
   139
      /// to the member of th container indexed by the integer _i.
marci@1152
   140
      Class(const int& _i) : i(_i) { }
marci@1031
   141
      /// Invalid constructor.
marci@1152
   142
      Class(const Invalid&) : i(-1) { }
marci@1152
   143
      friend bool operator<(const Class& x, const Class& y);
marci@1099
   144
      friend std::ostream& operator<<(std::ostream& os, 
marci@1152
   145
				      const Class& it);
marci@1152
   146
      bool operator==(const Class& node) const {return i == node.i;}
marci@1152
   147
      bool operator!=(const Class& node) const {return i != node.i;}
marci@1031
   148
    };
marci@1152
   149
    friend bool operator<(const Class& x, const Class& y) {
marci@1099
   150
      return (x.i < y.i);
marci@1099
   151
    }
marci@1099
   152
    friend std::ostream& operator<<(std::ostream& os, 
marci@1152
   153
				    const Class& it) {
marci@1099
   154
      os << it.i;
marci@1099
   155
      return os;
marci@1099
   156
    }
marci@1031
   157
    /// First member of class \c class_id.
marci@1152
   158
    Class& first(Class& it, int class_id) const {
marci@1031
   159
      it.i=tips[class_id].first;
marci@1031
   160
      return it;
marci@1031
   161
    }
marci@1031
   162
    /// Next member.
marci@1152
   163
    Class& next(Class& it) const {
marci@1031
   164
      it.i=nodes[it.i].next;
marci@1031
   165
      return it;
marci@1031
   166
    }
marci@1031
   167
    /// True iff the iterator is valid.
marci@1152
   168
    bool valid(const Class& it) const { return it.i!=-1; }
marci@1152
   169
marci@1152
   170
    class ClassIt : public Class {
marci@1152
   171
      const IterablePartition* iterable_partition;
marci@1152
   172
    public:
marci@1152
   173
      ClassIt() { }
marci@1152
   174
      ClassIt(Invalid i) : Class(i) { }
marci@1152
   175
      ClassIt(const IterablePartition& _iterable_partition, 
marci@1152
   176
	      const int& i) : iterable_partition(&_iterable_partition) {
marci@1152
   177
        _iterable_partition.first(*this, i);
marci@1152
   178
      }
marci@1152
   179
      ClassIt(const IterablePartition& _iterable_partition, 
marci@1152
   180
	      const Class& _class) : 
marci@1152
   181
	Class(_class), iterable_partition(&_iterable_partition) { }
marci@1152
   182
      ClassIt& operator++() {
marci@1152
   183
        iterable_partition->next(*this);
marci@1152
   184
        return *this;
marci@1152
   185
      }
marci@1152
   186
    };
marci@1152
   187
marci@1031
   188
  };
marci@1031
   189
marci@1097
   190
marci@1031
   191
  /*! \e
marci@1143
   192
    \todo kellenene uj iterable structure bele, mert ez nem az igazi
marci@1111
   193
    \todo A[x,y]-t cserel. Jobboldal, baloldal csere.
marci@1111
   194
    \todo LEKERDEZESEK!!!
marci@1111
   195
    \todo DOKSI!!!! Doxygen group!!!
marci@1111
   196
    The aim of this class is to give a general surface to different 
marci@1111
   197
    solvers, i.e. it makes possible to write algorithms using LP's, 
marci@1111
   198
    in which the solver can be changed to an other one easily.
marci@1112
   199
    \nosubgrouping
marci@1111
   200
  */
marci@1048
   201
  template <typename _Value>
marci@1031
   202
  class LPSolverBase {
marci@1112
   203
    
marci@1113
   204
    /*! @name Uncategorized functions and types (public members)
marci@1112
   205
    */
marci@1112
   206
    //@{
marci@1031
   207
  public:
marci@1112
   208
marci@1112
   209
    //UNCATEGORIZED
marci@1112
   210
marci@1031
   211
    /// \e
marci@1152
   212
    typedef IterablePartition<int> Rows;
marci@1152
   213
    /// \e
marci@1152
   214
    typedef IterablePartition<int> Cols;
marci@1152
   215
    /// \e
marci@1048
   216
    typedef _Value Value;
marci@1048
   217
    /// \e
marci@1152
   218
    typedef Rows::Class Row;
marci@1031
   219
    /// \e
marci@1152
   220
    typedef Cols::Class Col;
marci@1074
   221
  public:
marci@1031
   222
    /// \e
marci@1031
   223
    IterablePartition<int> row_iter_map;
marci@1031
   224
    /// \e
marci@1031
   225
    IterablePartition<int> col_iter_map;
marci@1031
   226
    /// \e
marci@1144
   227
    std::vector<Row> int_row_map;
marci@1143
   228
    /// \e
marci@1144
   229
    std::vector<Col> int_col_map;
marci@1143
   230
    /// \e
marci@1074
   231
    const int VALID_CLASS;
marci@1031
   232
    /// \e
marci@1074
   233
    const int INVALID_CLASS;
marci@1104
   234
    /// \e 
marci@1104
   235
    static const _Value INF;
marci@1031
   236
  public:
marci@1031
   237
    /// \e
marci@1031
   238
    LPSolverBase() : row_iter_map(2), 
marci@1031
   239
		     col_iter_map(2), 
marci@1074
   240
		     VALID_CLASS(0), INVALID_CLASS(1) { }
marci@1031
   241
    /// \e
marci@1031
   242
    virtual ~LPSolverBase() { }
marci@1112
   243
    //@}
marci@1081
   244
marci@1112
   245
    /*! @name Medium level interface (public members)
marci@1112
   246
      These functions appear in the low level and also in the high level 
marci@1112
   247
      interfaces thus these each of these functions have to be implemented 
marci@1112
   248
      only once in the different interfaces.
marci@1112
   249
      This means that these functions have to be reimplemented for all of the 
marci@1112
   250
      different lp solvers. These are basic functions, and have the same 
marci@1112
   251
      parameter lists in the low and high level interfaces. 
marci@1112
   252
    */
marci@1112
   253
    //@{
marci@1112
   254
  public:
marci@1081
   255
marci@1112
   256
    //UNCATEGORIZED FUNCTIONS
marci@1112
   257
marci@1031
   258
    /// \e
marci@1031
   259
    virtual void setMinimize() = 0;
marci@1031
   260
    /// \e
marci@1031
   261
    virtual void setMaximize() = 0;
marci@1081
   262
marci@1112
   263
    //SOLVER FUNCTIONS
marci@1081
   264
marci@1112
   265
    /// \e
marci@1112
   266
    virtual void solveSimplex() = 0;
marci@1112
   267
    /// \e
marci@1112
   268
    virtual void solvePrimalSimplex() = 0;
marci@1112
   269
    /// \e
marci@1112
   270
    virtual void solveDualSimplex() = 0;
marci@1112
   271
marci@1112
   272
    //SOLUTION RETRIEVING
marci@1112
   273
marci@1112
   274
    /// \e
marci@1112
   275
    virtual _Value getObjVal() = 0;
marci@1112
   276
marci@1112
   277
    //OTHER FUNCTIONS
marci@1112
   278
marci@1112
   279
    /// \e
marci@1112
   280
    virtual int rowNum() const = 0;
marci@1112
   281
    /// \e
marci@1112
   282
    virtual int colNum() const = 0;
marci@1112
   283
    /// \e
marci@1112
   284
    virtual int warmUp() = 0;
marci@1112
   285
    /// \e
marci@1112
   286
    virtual void printWarmUpStatus(int i) = 0;
marci@1112
   287
    /// \e
marci@1112
   288
    virtual int getPrimalStatus() = 0;
marci@1112
   289
    /// \e
marci@1112
   290
    virtual void printPrimalStatus(int i) = 0;
marci@1112
   291
    /// \e
marci@1112
   292
    virtual int getDualStatus() = 0;
marci@1112
   293
    /// \e
marci@1112
   294
    virtual void printDualStatus(int i) = 0;
marci@1144
   295
    /// Returns the status of the slack variable assigned to row \c row.
marci@1144
   296
    virtual int getRowStat(const Row& row) = 0;
marci@1112
   297
    /// \e
marci@1112
   298
    virtual void printRowStatus(int i) = 0;
marci@1144
   299
    /// Returns the status of the variable assigned to column \c col.
marci@1144
   300
    virtual int getColStat(const Col& col) = 0;
marci@1112
   301
    /// \e
marci@1112
   302
    virtual void printColStatus(int i) = 0;
marci@1112
   303
marci@1112
   304
    //@}
marci@1112
   305
marci@1112
   306
    /*! @name Low level interface (protected members)
marci@1112
   307
      Problem manipulating functions in the low level interface
marci@1112
   308
    */
marci@1112
   309
    //@{
marci@1074
   310
  protected:
marci@1112
   311
marci@1112
   312
    //MATRIX MANIPULATING FUNCTIONS
marci@1112
   313
marci@1031
   314
    /// \e
marci@1111
   315
    virtual int _addCol() = 0;
marci@1111
   316
    /// \e
marci@1074
   317
    virtual int _addRow() = 0;
marci@1031
   318
    /// \e
marci@1111
   319
    virtual void _eraseCol(int i) = 0;
marci@1111
   320
    /// \e
marci@1111
   321
    virtual void _eraseRow(int i) = 0;
marci@1081
   322
    /// \e
marci@1081
   323
    virtual void _setRowCoeffs(int i, 
marci@1104
   324
			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
marci@1081
   325
    /// \e
marci@1143
   326
    /// This routine modifies \c coeffs only by the \c push_back method.
marci@1143
   327
    virtual void _getRowCoeffs(int i, 
marci@1143
   328
			       std::vector<std::pair<int, _Value> >& coeffs) = 0;
marci@1152
   329
    /// \e
marci@1081
   330
    virtual void _setColCoeffs(int i, 
marci@1104
   331
			       const std::vector<std::pair<int, _Value> >& coeffs) = 0;
marci@1143
   332
    /// \e
marci@1143
   333
    /// This routine modifies \c coeffs only by the \c push_back method.
marci@1143
   334
    virtual void _getColCoeffs(int i, 
marci@1143
   335
			       std::vector<std::pair<int, _Value> >& coeffs) = 0;
marci@1081
   336
    /// \e
marci@1152
   337
    virtual void _setCoeff(int col, int row, _Value value) = 0;
marci@1152
   338
    /// \e
marci@1152
   339
    virtual _Value _getCoeff(int col, int row) = 0;
marci@1152
   340
    //  public:
marci@1152
   341
    //    /// \e
marci@1152
   342
    //    enum Bound { FREE, LOWER, UPPER, DOUBLE, FIXED };
marci@1081
   343
  protected:
marci@1081
   344
    /// \e
marci@1110
   345
    /// The lower bound of a variable (column) have to be given by an 
marci@1110
   346
    /// extended number of type _Value, i.e. a finite number of type 
marci@1110
   347
    /// _Value or -INF.
marci@1110
   348
    virtual void _setColLowerBound(int i, _Value value) = 0;
marci@1110
   349
    /// \e
marci@1111
   350
    /// The lower bound of a variable (column) is an 
marci@1111
   351
    /// extended number of type _Value, i.e. a finite number of type 
marci@1111
   352
    /// _Value or -INF.
marci@1111
   353
    virtual _Value _getColLowerBound(int i) = 0;
marci@1111
   354
    /// \e
marci@1110
   355
    /// The upper bound of a variable (column) have to be given by an 
marci@1110
   356
    /// extended number of type _Value, i.e. a finite number of type 
marci@1110
   357
    /// _Value or INF.
marci@1110
   358
    virtual void _setColUpperBound(int i, _Value value) = 0;
marci@1110
   359
    /// \e
marci@1110
   360
    /// The upper bound of a variable (column) is an 
marci@1110
   361
    /// extended number of type _Value, i.e. a finite number of type 
marci@1110
   362
    /// _Value or INF.
marci@1110
   363
    virtual _Value _getColUpperBound(int i) = 0;
marci@1110
   364
    /// \e
marci@1111
   365
    /// The lower bound of a linear expression (row) have to be given by an 
marci@1111
   366
    /// extended number of type _Value, i.e. a finite number of type 
marci@1111
   367
    /// _Value or -INF.
marci@1111
   368
    virtual void _setRowLowerBound(int i, _Value value) = 0;
marci@1081
   369
    /// \e
marci@1111
   370
    /// The lower bound of a linear expression (row) is an 
marci@1111
   371
    /// extended number of type _Value, i.e. a finite number of type 
marci@1111
   372
    /// _Value or -INF.
marci@1111
   373
    virtual _Value _getRowLowerBound(int i) = 0;
marci@1111
   374
    /// \e
marci@1111
   375
    /// The upper bound of a linear expression (row) have to be given by an 
marci@1111
   376
    /// extended number of type _Value, i.e. a finite number of type 
marci@1111
   377
    /// _Value or INF.
marci@1111
   378
    virtual void _setRowUpperBound(int i, _Value value) = 0;
marci@1111
   379
    /// \e
marci@1111
   380
    /// The upper bound of a linear expression (row) is an 
marci@1111
   381
    /// extended number of type _Value, i.e. a finite number of type 
marci@1111
   382
    /// _Value or INF.
marci@1111
   383
    virtual _Value _getRowUpperBound(int i) = 0;
marci@1081
   384
    /// \e
marci@1152
   385
    virtual void _setObjCoeff(int i, _Value obj_coef) = 0;
marci@1081
   386
    /// \e
marci@1152
   387
    virtual _Value _getObjCoeff(int i) = 0;
marci@1112
   388
    
marci@1112
   389
    //SOLUTION RETRIEVING
marci@1081
   390
marci@1111
   391
    /// \e
marci@1081
   392
    virtual _Value _getPrimal(int i) = 0;
marci@1112
   393
    //@}
marci@1112
   394
    
marci@1112
   395
    /*! @name High level interface (public members)
marci@1112
   396
      Problem manipulating functions in the high level interface
marci@1112
   397
    */
marci@1112
   398
    //@{
marci@1112
   399
  public:
marci@1081
   400
marci@1112
   401
    //MATRIX MANIPULATING FUNCTIONS
marci@1081
   402
marci@1074
   403
    /// \e
marci@1144
   404
    Col addCol() {
marci@1074
   405
      int i=_addCol();  
marci@1144
   406
      Col col;
marci@1144
   407
      col_iter_map.first(col, INVALID_CLASS);
marci@1144
   408
      if (col_iter_map.valid(col)) { //van hasznalhato hely
marci@1144
   409
	col_iter_map.set(col, INVALID_CLASS, VALID_CLASS);
marci@1144
   410
	col_iter_map[col]=i;
marci@1074
   411
      } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@1144
   412
	col=col_iter_map.push_back(i, VALID_CLASS);
marci@1074
   413
      }
marci@1144
   414
      int_col_map.push_back(col);
marci@1144
   415
      return col;
marci@1074
   416
    }
marci@1074
   417
    /// \e
marci@1144
   418
    Row addRow() {
marci@1111
   419
      int i=_addRow();
marci@1144
   420
      Row row;
marci@1144
   421
      row_iter_map.first(row, INVALID_CLASS);
marci@1144
   422
      if (row_iter_map.valid(row)) { //van hasznalhato hely
marci@1144
   423
	row_iter_map.set(row, INVALID_CLASS, VALID_CLASS);
marci@1144
   424
	row_iter_map[row]=i;
marci@1111
   425
      } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@1144
   426
	row=row_iter_map.push_back(i, VALID_CLASS);
marci@1031
   427
      }
marci@1144
   428
      int_row_map.push_back(row);
marci@1144
   429
      return row;
marci@1074
   430
    }
marci@1074
   431
    /// \e
marci@1144
   432
    void eraseCol(const Col& col) {
marci@1144
   433
      col_iter_map.set(col, VALID_CLASS, INVALID_CLASS);
marci@1074
   434
      int cols[2];
marci@1144
   435
      cols[1]=col_iter_map[col];
marci@1074
   436
      _eraseCol(cols[1]);
marci@1144
   437
      col_iter_map[col]=0; //glpk specifikus, de kell ez??
marci@1144
   438
      Col it;
marci@1074
   439
      for (col_iter_map.first(it, VALID_CLASS); 
marci@1074
   440
	   col_iter_map.valid(it); col_iter_map.next(it)) {
marci@1074
   441
	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
marci@1074
   442
      }
marci@1143
   443
      int_col_map.erase(int_col_map.begin()+cols[1]);
marci@1031
   444
    }
marci@1031
   445
    /// \e
marci@1144
   446
    void eraseRow(const Row& row) {
marci@1144
   447
      row_iter_map.set(row, VALID_CLASS, INVALID_CLASS);
marci@1074
   448
      int rows[2];
marci@1144
   449
      rows[1]=row_iter_map[row];
marci@1074
   450
      _eraseRow(rows[1]);
marci@1144
   451
      row_iter_map[row]=0; //glpk specifikus, de kell ez??
marci@1144
   452
      Row it;
marci@1074
   453
      for (row_iter_map.first(it, VALID_CLASS); 
marci@1074
   454
	   row_iter_map.valid(it); row_iter_map.next(it)) {
marci@1074
   455
	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
marci@1074
   456
      }
marci@1143
   457
      int_row_map.erase(int_row_map.begin()+rows[1]);
marci@1074
   458
    }
marci@1031
   459
    /// \e
marci@1152
   460
    void setCoeff(Col col, Row row, _Value value) {
marci@1152
   461
      _setCoeff(col_iter_map[col], row_iter_map[row], value);
marci@1152
   462
    }
marci@1152
   463
    /// \e
marci@1152
   464
    _Value getCoeff(Col col, Row row) {
marci@1152
   465
      return _getCoeff(col_iter_map[col], row_iter_map[row], value);
marci@1152
   466
    }
marci@1152
   467
    /// \e
marci@1144
   468
    void setColLowerBound(Col col, _Value lo) {
marci@1144
   469
      _setColLowerBound(col_iter_map[col], lo);
marci@1111
   470
    }
marci@1111
   471
    /// \e
marci@1144
   472
    _Value getColLowerBound(Col col) {
marci@1144
   473
      return _getColLowerBound(col_iter_map[col]);
marci@1111
   474
    }
marci@1111
   475
    /// \e
marci@1144
   476
    void setColUpperBound(Col col, _Value up) {
marci@1144
   477
      _setColUpperBound(col_iter_map[col], up);
marci@1110
   478
    }
marci@1110
   479
    /// \e
marci@1144
   480
    _Value getColUpperBound(Col col) {      
marci@1144
   481
      return _getColUpperBound(col_iter_map[col]);
marci@1111
   482
    }
marci@1111
   483
    /// \e
marci@1144
   484
    void setRowLowerBound(Row row, _Value lo) {
marci@1144
   485
      _setRowLowerBound(row_iter_map[row], lo);
marci@1110
   486
    }
marci@1110
   487
    /// \e
marci@1144
   488
    _Value getRowLowerBound(Row row) {
marci@1144
   489
      return _getRowLowerBound(row_iter_map[row]);
marci@1110
   490
    }
marci@1110
   491
    /// \e
marci@1144
   492
    void setRowUpperBound(Row row, _Value up) {
marci@1144
   493
      _setRowUpperBound(row_iter_map[row], up);
marci@1081
   494
    }
marci@1031
   495
    /// \e
marci@1144
   496
    _Value getRowUpperBound(Row row) {      
marci@1144
   497
      return _getRowUpperBound(row_iter_map[row]);
marci@1111
   498
    }
marci@1111
   499
    /// \e
marci@1152
   500
    void setObjCoeff(const Col& col, _Value obj_coef) {
marci@1152
   501
      _setObjCoeff(col_iter_map[col], obj_coef);
marci@1111
   502
    }
marci@1111
   503
    /// \e
marci@1152
   504
    _Value getObjCoeff(const Col& col) {
marci@1152
   505
      return _getObjCoeff(col_iter_map[col]);
marci@1081
   506
    }
marci@1081
   507
marci@1112
   508
    //SOLUTION RETRIEVING FUNCTIONS
marci@1112
   509
marci@1112
   510
    /// \e
marci@1144
   511
    _Value getPrimal(const Col& col) {
marci@1144
   512
      return _getPrimal(col_iter_map[col]);
marci@1112
   513
    }    
marci@1112
   514
marci@1112
   515
    //@}
marci@1112
   516
marci@1112
   517
    /*! @name User friend interface
marci@1112
   518
      Problem manipulating functions in the user friend interface
marci@1112
   519
    */
marci@1112
   520
    //@{
marci@1112
   521
marci@1112
   522
    //EXPRESSION TYPES
marci@1099
   523
marci@1099
   524
    /// \e
marci@1144
   525
    typedef Expr<Col, _Value> Expression;
marci@1099
   526
    /// \e
marci@1144
   527
    typedef Expr<Row, _Value> DualExpression;
marci@1144
   528
    /// \e
marci@1144
   529
    typedef Constr<Col, _Value> Constraint;
marci@1112
   530
marci@1112
   531
    //MATRIX MANIPULATING FUNCTIONS
marci@1112
   532
marci@1099
   533
    /// \e
marci@1144
   534
    void setRowCoeffs(Row row, const Expression& expr) {
marci@1099
   535
      std::vector<std::pair<int, _Value> > row_coeffs;
marci@1099
   536
      for(typename Expression::Data::const_iterator i=expr.data.begin(); 
marci@1099
   537
	  i!=expr.data.end(); ++i) {
marci@1099
   538
	row_coeffs.push_back(std::make_pair
marci@1099
   539
			     (col_iter_map[(*i).first], (*i).second));
marci@1099
   540
      }
marci@1144
   541
      _setRowCoeffs(row_iter_map[row], row_coeffs);
marci@1144
   542
    }
marci@1144
   543
    /// \e 
marci@1144
   544
    void setRow(Row row, const Constraint& constr) {
marci@1144
   545
      setRowCoeffs(row, constr.expr);
marci@1144
   546
      setRowLowerBound(row, constr.lo);
marci@1144
   547
      setRowUpperBound(row, constr.up);
marci@1144
   548
    }
marci@1144
   549
    /// \e 
marci@1144
   550
    Row addRow(const Constraint& constr) {
marci@1144
   551
      Row row=addRow();
marci@1144
   552
      setRowCoeffs(row, constr.expr);
marci@1144
   553
      setRowLowerBound(row, constr.lo);
marci@1144
   554
      setRowUpperBound(row, constr.up);
marci@1144
   555
      return row;
marci@1099
   556
    }
marci@1099
   557
    /// \e
marci@1143
   558
    /// This routine modifies \c expr by only adding to it.
marci@1144
   559
    void getRowCoeffs(Row row, Expression& expr) {
marci@1143
   560
      std::vector<std::pair<int, _Value> > row_coeffs;
marci@1144
   561
      _getRowCoeffs(row_iter_map[row], row_coeffs);
marci@1143
   562
      for(typename std::vector<std::pair<int, _Value> >::const_iterator 
marci@1143
   563
 	    i=row_coeffs.begin(); i!=row_coeffs.end(); ++i) {
marci@1143
   564
 	expr+= (*i).second*int_col_map[(*i).first];
marci@1143
   565
      }
marci@1143
   566
    }
marci@1143
   567
    /// \e
marci@1144
   568
    void setColCoeffs(Col col, const DualExpression& expr) {
marci@1099
   569
      std::vector<std::pair<int, _Value> > col_coeffs;
marci@1099
   570
      for(typename DualExpression::Data::const_iterator i=expr.data.begin(); 
marci@1099
   571
	  i!=expr.data.end(); ++i) {
marci@1099
   572
	col_coeffs.push_back(std::make_pair
marci@1099
   573
			     (row_iter_map[(*i).first], (*i).second));
marci@1099
   574
      }
marci@1144
   575
      _setColCoeffs(col_iter_map[col], col_coeffs);
marci@1099
   576
    }
marci@1099
   577
    /// \e
marci@1143
   578
    /// This routine modifies \c expr by only adding to it.
marci@1144
   579
    void getColCoeffs(Col col, DualExpression& expr) {
marci@1143
   580
      std::vector<std::pair<int, _Value> > col_coeffs;
marci@1144
   581
      _getColCoeffs(col_iter_map[col], col_coeffs);
marci@1143
   582
      for(typename std::vector<std::pair<int, _Value> >::const_iterator 
marci@1143
   583
 	    i=col_coeffs.begin(); i!=col_coeffs.end(); ++i) {
marci@1143
   584
 	expr+= (*i).second*int_row_map[(*i).first];
marci@1143
   585
      }
marci@1143
   586
    }
marci@1143
   587
    /// \e
marci@1099
   588
    void setObjCoeffs(const Expression& expr) {
marci@1152
   589
      // writing zero everywhere
marci@1152
   590
      for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
marci@1152
   591
	setObjCoeff(it, 0.0);
marci@1152
   592
      // writing the data needed
marci@1099
   593
      for(typename Expression::Data::const_iterator i=expr.data.begin(); 
marci@1099
   594
	  i!=expr.data.end(); ++i) {
marci@1152
   595
	setObjCoeff((*i).first, (*i).second);
marci@1099
   596
      }
marci@1099
   597
    }
marci@1143
   598
    /// \e
marci@1143
   599
    /// This routine modifies \c expr by only adding to it.
marci@1143
   600
    void getObjCoeffs(Expression& expr) {
marci@1152
   601
      for(Cols::ClassIt it(col_iter_map, VALID_CLASS); it!=INVALID; ++it)
marci@1152
   602
	expr+=getObjCoeff(it)*it;
marci@1152
   603
    }
marci@1152
   604
    //@}
marci@1152
   605
marci@1152
   606
marci@1152
   607
    /*! @name MIP functions and types (public members)
marci@1152
   608
    */
marci@1152
   609
    //@{
marci@1152
   610
  public:
marci@1152
   611
    /// \e
marci@1152
   612
    virtual void solveBandB() = 0;
marci@1152
   613
    /// \e
marci@1152
   614
    virtual void setLP() = 0;
marci@1152
   615
    /// \e
marci@1152
   616
    virtual void setMIP() = 0;
marci@1152
   617
  protected:
marci@1152
   618
   /// \e
marci@1152
   619
    virtual void _setColCont(int i) = 0;
marci@1152
   620
    /// \e
marci@1152
   621
    virtual void _setColInt(int i) = 0;
marci@1153
   622
    /// \e
marci@1153
   623
    virtual _Value _getMIPPrimal(int i) = 0;
marci@1152
   624
  public:
marci@1152
   625
    /// \e
marci@1152
   626
    void setColCont(Col col) {
marci@1152
   627
      _setColCont(col_iter_map[col]);
marci@1152
   628
    }
marci@1152
   629
    /// \e
marci@1152
   630
    void setColInt(Col col) {
marci@1152
   631
      _setColInt(col_iter_map[col]);
marci@1143
   632
    }
marci@1153
   633
    /// \e
marci@1153
   634
    _Value getMIPPrimal(Col col) {
marci@1153
   635
      return _getMIPPrimal(col_iter_map[col]);
marci@1153
   636
    }
marci@1112
   637
    //@}
marci@1031
   638
  };
marci@1031
   639
  
marci@1104
   640
  template <typename _Value>
marci@1104
   641
  const _Value LPSolverBase<_Value>::INF=std::numeric_limits<_Value>::infinity();
marci@1104
   642
marci@1048
   643
marci@1111
   644
  /// \brief Wrapper for GLPK solver
marci@1031
   645
  /// 
marci@1111
   646
  /// This class implements a lemon wrapper for GLPK.
marci@1081
   647
  class LPGLPK : public LPSolverBase<double> {
marci@1031
   648
  public:
marci@1048
   649
    typedef LPSolverBase<double> Parent;
marci@1031
   650
marci@1031
   651
  public:
marci@1031
   652
    /// \e
marci@1031
   653
    LPX* lp;
marci@1031
   654
marci@1031
   655
  public:
marci@1031
   656
    /// \e
marci@1081
   657
    LPGLPK() : Parent(), 
marci@1031
   658
			lp(lpx_create_prob()) {
marci@1144
   659
      int_row_map.push_back(Row());
marci@1144
   660
      int_col_map.push_back(Col());
marci@1031
   661
      lpx_set_int_parm(lp, LPX_K_DUAL, 1);
marci@1031
   662
    }
marci@1031
   663
    /// \e
marci@1081
   664
    ~LPGLPK() {
marci@1031
   665
      lpx_delete_prob(lp);
marci@1031
   666
    }
marci@1081
   667
marci@1081
   668
    //MATRIX INDEPEDENT MANIPULATING FUNCTIONS
marci@1081
   669
marci@1031
   670
    /// \e
marci@1031
   671
    void setMinimize() { 
marci@1031
   672
      lpx_set_obj_dir(lp, LPX_MIN);
marci@1031
   673
    }
marci@1031
   674
    /// \e
marci@1031
   675
    void setMaximize() { 
marci@1031
   676
      lpx_set_obj_dir(lp, LPX_MAX);
marci@1031
   677
    }
marci@1081
   678
marci@1081
   679
    //LOW LEVEL INTERFACE, MATRIX MANIPULATING FUNCTIONS
marci@1081
   680
marci@1074
   681
  protected:
marci@1031
   682
    /// \e
marci@1074
   683
    int _addCol() { 
marci@1110
   684
      int i=lpx_add_cols(lp, 1);
marci@1110
   685
      _setColLowerBound(i, -INF);
marci@1110
   686
      _setColUpperBound(i, INF);
marci@1110
   687
      return i;
marci@1031
   688
    }
marci@1031
   689
    /// \e
marci@1074
   690
    int _addRow() { 
marci@1110
   691
      int i=lpx_add_rows(lp, 1);
marci@1110
   692
      return i;
marci@1074
   693
    }
marci@1074
   694
    /// \e
marci@1081
   695
    virtual void _setRowCoeffs(int i, 
marci@1104
   696
			       const std::vector<std::pair<int, double> >& coeffs) {
marci@1074
   697
      int mem_length=1+colNum();
marci@1074
   698
      int* indices = new int[mem_length];
marci@1074
   699
      double* doubles = new double[mem_length];
marci@1074
   700
      int length=0;
marci@1074
   701
      for (std::vector<std::pair<int, double> >::
marci@1074
   702
	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
marci@1074
   703
	++length;
marci@1074
   704
	indices[length]=it->first;
marci@1074
   705
	doubles[length]=it->second;
marci@1031
   706
      }
marci@1074
   707
      lpx_set_mat_row(lp, i, length, indices, doubles);
marci@1074
   708
      delete [] indices;
marci@1074
   709
      delete [] doubles;
marci@1031
   710
    }
marci@1074
   711
    /// \e
marci@1143
   712
    virtual void _getRowCoeffs(int i, 
marci@1143
   713
			       std::vector<std::pair<int, double> >& coeffs) {
marci@1143
   714
      int mem_length=1+colNum();
marci@1143
   715
      int* indices = new int[mem_length];
marci@1143
   716
      double* doubles = new double[mem_length];
marci@1143
   717
      int length=lpx_get_mat_row(lp, i, indices, doubles);
marci@1143
   718
      for (int i=1; i<=length; ++i) {
marci@1143
   719
	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
marci@1143
   720
      }
marci@1143
   721
      delete [] indices;
marci@1143
   722
      delete [] doubles;
marci@1143
   723
    }
marci@1143
   724
    /// \e
marci@1081
   725
    virtual void _setColCoeffs(int i, 
marci@1104
   726
			       const std::vector<std::pair<int, double> >& coeffs) {
marci@1074
   727
      int mem_length=1+rowNum();
marci@1074
   728
      int* indices = new int[mem_length];
marci@1074
   729
      double* doubles = new double[mem_length];
marci@1074
   730
      int length=0;
marci@1074
   731
      for (std::vector<std::pair<int, double> >::
marci@1074
   732
	     const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
marci@1074
   733
	++length;
marci@1074
   734
	indices[length]=it->first;
marci@1074
   735
	doubles[length]=it->second;
marci@1074
   736
      }
marci@1074
   737
      lpx_set_mat_col(lp, i, length, indices, doubles);
marci@1074
   738
      delete [] indices;
marci@1074
   739
      delete [] doubles;
marci@1031
   740
    }
marci@1031
   741
    /// \e
marci@1143
   742
    virtual void _getColCoeffs(int i, 
marci@1143
   743
			       std::vector<std::pair<int, double> >& coeffs) {
marci@1143
   744
      int mem_length=1+rowNum();
marci@1143
   745
      int* indices = new int[mem_length];
marci@1143
   746
      double* doubles = new double[mem_length];
marci@1143
   747
      int length=lpx_get_mat_col(lp, i, indices, doubles);
marci@1143
   748
      for (int i=1; i<=length; ++i) {
marci@1143
   749
	coeffs.push_back(std::make_pair(indices[i], doubles[i]));
marci@1143
   750
      }
marci@1143
   751
      delete [] indices;
marci@1143
   752
      delete [] doubles;
marci@1143
   753
    }
marci@1143
   754
    /// \e
marci@1074
   755
    virtual void _eraseCol(int i) {
marci@1031
   756
      int cols[2];
marci@1074
   757
      cols[1]=i;
marci@1031
   758
      lpx_del_cols(lp, 1, cols);
marci@1031
   759
    }
marci@1074
   760
    virtual void _eraseRow(int i) {
marci@1031
   761
      int rows[2];
marci@1074
   762
      rows[1]=i;
marci@1031
   763
      lpx_del_rows(lp, 1, rows);
marci@1031
   764
    }
marci@1152
   765
    void _setCoeff(int col, int row, double value) {
marci@1152
   766
      /// FIXME not yet implemented
marci@1152
   767
    }
marci@1152
   768
    double _getCoeff(int col, int row) {
marci@1152
   769
      /// FIXME not yet implemented
marci@1152
   770
      return 0.0;
marci@1152
   771
    }
marci@1110
   772
    virtual void _setColLowerBound(int i, double lo) {
marci@1110
   773
      if (lo==INF) {
marci@1110
   774
	//FIXME error
marci@1110
   775
      }
marci@1110
   776
      int b=lpx_get_col_type(lp, i);
marci@1110
   777
      double up=lpx_get_col_ub(lp, i);	
marci@1110
   778
      if (lo==-INF) {
marci@1110
   779
	switch (b) {
marci@1110
   780
	case LPX_FR:
marci@1110
   781
	case LPX_LO:
marci@1110
   782
	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
marci@1110
   783
	  break;
marci@1110
   784
	case LPX_UP:
marci@1110
   785
	  break;
marci@1110
   786
	case LPX_DB:
marci@1110
   787
	case LPX_FX:
marci@1110
   788
	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
marci@1110
   789
	  break;
marci@1110
   790
	default: ;
marci@1110
   791
	  //FIXME error
marci@1110
   792
	}
marci@1110
   793
      } else {
marci@1110
   794
	switch (b) {
marci@1110
   795
	case LPX_FR:
marci@1110
   796
	case LPX_LO:
marci@1110
   797
	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
marci@1110
   798
	  break;
marci@1110
   799
	case LPX_UP:	  
marci@1110
   800
	case LPX_DB:
marci@1110
   801
	case LPX_FX:
marci@1110
   802
	  if (lo==up) 
marci@1110
   803
	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
marci@1110
   804
	  else 
marci@1110
   805
	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
marci@1110
   806
	  break;
marci@1110
   807
	default: ;
marci@1110
   808
	  //FIXME error
marci@1110
   809
	}
marci@1110
   810
      }
marci@1110
   811
    }
marci@1111
   812
    virtual double _getColLowerBound(int i) {
marci@1111
   813
      int b=lpx_get_col_type(lp, i);
marci@1111
   814
      switch (b) {
marci@1111
   815
      case LPX_FR:
marci@1111
   816
	return -INF;
marci@1111
   817
      case LPX_LO:
marci@1111
   818
	return lpx_get_col_lb(lp, i);
marci@1111
   819
      case LPX_UP:
marci@1111
   820
	return -INF;
marci@1111
   821
      case LPX_DB:
marci@1111
   822
      case LPX_FX:
marci@1111
   823
	return lpx_get_col_lb(lp, i);
marci@1111
   824
      default: ;
marci@1111
   825
	//FIXME error
marci@1111
   826
	return 0.0;
marci@1111
   827
      }
marci@1111
   828
    }
marci@1110
   829
    virtual void _setColUpperBound(int i, double up) {
marci@1110
   830
      if (up==-INF) {
marci@1110
   831
	//FIXME error
marci@1110
   832
      }
marci@1110
   833
      int b=lpx_get_col_type(lp, i);
marci@1110
   834
      double lo=lpx_get_col_lb(lp, i);
marci@1110
   835
      if (up==INF) {
marci@1110
   836
	switch (b) {
marci@1110
   837
	case LPX_FR:
marci@1110
   838
	case LPX_LO:
marci@1110
   839
	  break;
marci@1110
   840
	case LPX_UP:
marci@1110
   841
	  lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
marci@1110
   842
	  break;
marci@1110
   843
	case LPX_DB:
marci@1110
   844
	case LPX_FX:
marci@1110
   845
	  lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
marci@1110
   846
	  break;
marci@1110
   847
	default: ;
marci@1110
   848
	  //FIXME error
marci@1110
   849
	}
marci@1110
   850
      } else {
marci@1110
   851
	switch (b) {
marci@1110
   852
	case LPX_FR:
marci@1110
   853
	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
marci@1110
   854
	case LPX_LO:
marci@1110
   855
	  if (lo==up) 
marci@1110
   856
	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
marci@1110
   857
	  else
marci@1110
   858
	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
marci@1110
   859
	  break;
marci@1110
   860
	case LPX_UP:
marci@1110
   861
	  lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
marci@1110
   862
	  break;
marci@1110
   863
	case LPX_DB:
marci@1110
   864
	case LPX_FX:
marci@1110
   865
	  if (lo==up) 
marci@1110
   866
	    lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
marci@1110
   867
	  else 
marci@1110
   868
	    lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
marci@1110
   869
	  break;
marci@1110
   870
	default: ;
marci@1110
   871
	  //FIXME error
marci@1110
   872
	}
marci@1110
   873
      }
marci@1110
   874
    }
marci@1110
   875
    virtual double _getColUpperBound(int i) {
marci@1110
   876
      int b=lpx_get_col_type(lp, i);
marci@1110
   877
      switch (b) {
marci@1110
   878
      case LPX_FR:
marci@1110
   879
      case LPX_LO:
marci@1110
   880
	return INF;
marci@1110
   881
      case LPX_UP:
marci@1110
   882
      case LPX_DB:
marci@1110
   883
      case LPX_FX:
marci@1110
   884
	return lpx_get_col_ub(lp, i);
marci@1110
   885
      default: ;
marci@1110
   886
	//FIXME error
marci@1110
   887
	return 0.0;
marci@1110
   888
      }
marci@1110
   889
    }
marci@1111
   890
    virtual void _setRowLowerBound(int i, double lo) {
marci@1111
   891
      if (lo==INF) {
marci@1111
   892
	//FIXME error
marci@1081
   893
      }
marci@1111
   894
      int b=lpx_get_row_type(lp, i);
marci@1111
   895
      double up=lpx_get_row_ub(lp, i);	
marci@1111
   896
      if (lo==-INF) {
marci@1111
   897
	switch (b) {
marci@1111
   898
	case LPX_FR:
marci@1111
   899
	case LPX_LO:
marci@1111
   900
	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
marci@1111
   901
	  break;
marci@1111
   902
	case LPX_UP:
marci@1111
   903
	  break;
marci@1111
   904
	case LPX_DB:
marci@1111
   905
	case LPX_FX:
marci@1111
   906
	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
marci@1111
   907
	  break;
marci@1111
   908
	default: ;
marci@1111
   909
	  //FIXME error
marci@1111
   910
	}
marci@1111
   911
      } else {
marci@1111
   912
	switch (b) {
marci@1111
   913
	case LPX_FR:
marci@1111
   914
	case LPX_LO:
marci@1111
   915
	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
marci@1111
   916
	  break;
marci@1111
   917
	case LPX_UP:	  
marci@1111
   918
	case LPX_DB:
marci@1111
   919
	case LPX_FX:
marci@1111
   920
	  if (lo==up) 
marci@1111
   921
	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
marci@1111
   922
	  else 
marci@1111
   923
	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
marci@1111
   924
	  break;
marci@1111
   925
	default: ;
marci@1111
   926
	  //FIXME error
marci@1111
   927
	}
marci@1081
   928
      }
marci@1111
   929
    }
marci@1111
   930
    virtual double _getRowLowerBound(int i) {
marci@1111
   931
      int b=lpx_get_row_type(lp, i);
marci@1111
   932
      switch (b) {
marci@1111
   933
      case LPX_FR:
marci@1111
   934
	return -INF;
marci@1111
   935
      case LPX_LO:
marci@1111
   936
	return lpx_get_row_lb(lp, i);
marci@1111
   937
      case LPX_UP:
marci@1111
   938
	return -INF;
marci@1111
   939
      case LPX_DB:
marci@1111
   940
      case LPX_FX:
marci@1111
   941
	return lpx_get_row_lb(lp, i);
marci@1111
   942
      default: ;
marci@1111
   943
	//FIXME error
marci@1111
   944
	return 0.0;
marci@1111
   945
      }
marci@1111
   946
    }
marci@1111
   947
    virtual void _setRowUpperBound(int i, double up) {
marci@1111
   948
      if (up==-INF) {
marci@1111
   949
	//FIXME error
marci@1111
   950
      }
marci@1111
   951
      int b=lpx_get_row_type(lp, i);
marci@1111
   952
      double lo=lpx_get_row_lb(lp, i);
marci@1111
   953
      if (up==INF) {
marci@1111
   954
	switch (b) {
marci@1111
   955
	case LPX_FR:
marci@1111
   956
	case LPX_LO:
marci@1111
   957
	  break;
marci@1111
   958
	case LPX_UP:
marci@1111
   959
	  lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
marci@1111
   960
	  break;
marci@1111
   961
	case LPX_DB:
marci@1111
   962
	case LPX_FX:
marci@1111
   963
	  lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
marci@1111
   964
	  break;
marci@1111
   965
	default: ;
marci@1111
   966
	  //FIXME error
marci@1111
   967
	}
marci@1111
   968
      } else {
marci@1111
   969
	switch (b) {
marci@1111
   970
	case LPX_FR:
marci@1111
   971
	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
marci@1111
   972
	case LPX_LO:
marci@1111
   973
	  if (lo==up) 
marci@1111
   974
	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
marci@1111
   975
	  else
marci@1111
   976
	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
marci@1111
   977
	  break;
marci@1111
   978
	case LPX_UP:
marci@1111
   979
	  lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
marci@1111
   980
	  break;
marci@1111
   981
	case LPX_DB:
marci@1111
   982
	case LPX_FX:
marci@1111
   983
	  if (lo==up) 
marci@1111
   984
	    lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
marci@1111
   985
	  else 
marci@1111
   986
	    lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
marci@1111
   987
	  break;
marci@1111
   988
	default: ;
marci@1111
   989
	  //FIXME error
marci@1111
   990
	}
marci@1111
   991
      }
marci@1111
   992
    }
marci@1111
   993
    virtual double _getRowUpperBound(int i) {
marci@1111
   994
      int b=lpx_get_row_type(lp, i);
marci@1111
   995
      switch (b) {
marci@1111
   996
      case LPX_FR:
marci@1111
   997
      case LPX_LO:
marci@1111
   998
	return INF;
marci@1111
   999
      case LPX_UP:
marci@1111
  1000
      case LPX_DB:
marci@1111
  1001
      case LPX_FX:
marci@1111
  1002
	return lpx_get_row_ub(lp, i);
marci@1111
  1003
      default: ;
marci@1111
  1004
	//FIXME error
marci@1111
  1005
	return 0.0;
marci@1111
  1006
      }
marci@1111
  1007
    }
marci@1031
  1008
    /// \e
marci@1152
  1009
    virtual double _getObjCoeff(int i) { 
marci@1081
  1010
      return lpx_get_obj_coef(lp, i);
marci@1031
  1011
    }
marci@1031
  1012
    /// \e
marci@1152
  1013
    virtual void _setObjCoeff(int i, double obj_coef) { 
marci@1081
  1014
      lpx_set_obj_coef(lp, i, obj_coef);
marci@1031
  1015
    }
marci@1081
  1016
  public:
marci@1031
  1017
    /// \e
marci@1031
  1018
    void solveSimplex() { lpx_simplex(lp); }
marci@1031
  1019
    /// \e
marci@1031
  1020
    void solvePrimalSimplex() { lpx_simplex(lp); }
marci@1031
  1021
    /// \e
marci@1031
  1022
    void solveDualSimplex() { lpx_simplex(lp); }
marci@1081
  1023
  protected:
marci@1081
  1024
    virtual double _getPrimal(int i) {
marci@1081
  1025
      return lpx_get_col_prim(lp, i);
marci@1031
  1026
    }
marci@1081
  1027
  public:
marci@1031
  1028
    /// \e
marci@1031
  1029
    double getObjVal() { return lpx_get_obj_val(lp); }
marci@1031
  1030
    /// \e
marci@1031
  1031
    int rowNum() const { return lpx_get_num_rows(lp); }
marci@1031
  1032
    /// \e
marci@1031
  1033
    int colNum() const { return lpx_get_num_cols(lp); }
marci@1031
  1034
    /// \e
marci@1031
  1035
    int warmUp() { return lpx_warm_up(lp); }
marci@1031
  1036
    /// \e
marci@1031
  1037
    void printWarmUpStatus(int i) {
marci@1031
  1038
      switch (i) {
marci@1031
  1039
      case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
marci@1031
  1040
      case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
marci@1031
  1041
      case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
marci@1031
  1042
      case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
marci@1031
  1043
      }
marci@1031
  1044
    }
marci@1031
  1045
    /// \e
marci@1031
  1046
    int getPrimalStatus() { return lpx_get_prim_stat(lp); }
marci@1031
  1047
    /// \e
marci@1031
  1048
    void printPrimalStatus(int i) {
marci@1031
  1049
      switch (i) {
marci@1031
  1050
      case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
marci@1031
  1051
      case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
marci@1031
  1052
      case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
marci@1031
  1053
      case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
marci@1031
  1054
      }
marci@1031
  1055
    }
marci@1031
  1056
    /// \e
marci@1031
  1057
    int getDualStatus() { return lpx_get_dual_stat(lp); }
marci@1031
  1058
    /// \e
marci@1031
  1059
    void printDualStatus(int i) {
marci@1031
  1060
      switch (i) {
marci@1031
  1061
      case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
marci@1031
  1062
      case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
marci@1031
  1063
      case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
marci@1031
  1064
      case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
marci@1031
  1065
      }
marci@1031
  1066
    }
marci@1144
  1067
    /// Returns the status of the slack variable assigned to row \c row.
marci@1144
  1068
    int getRowStat(const Row& row) { 
marci@1144
  1069
      return lpx_get_row_stat(lp, row_iter_map[row]); 
marci@1031
  1070
    }
marci@1031
  1071
    /// \e
marci@1031
  1072
    void printRowStatus(int i) {
marci@1031
  1073
      switch (i) {
marci@1031
  1074
      case LPX_BS: cout << "LPX_BS" << endl; break;
marci@1031
  1075
      case LPX_NL: cout << "LPX_NL" << endl; break;	
marci@1031
  1076
      case LPX_NU: cout << "LPX_NU" << endl; break;
marci@1031
  1077
      case LPX_NF: cout << "LPX_NF" << endl; break;
marci@1031
  1078
      case LPX_NS: cout << "LPX_NS" << endl; break;
marci@1031
  1079
      }
marci@1031
  1080
    }
marci@1144
  1081
    /// Returns the status of the variable assigned to column \c col.
marci@1144
  1082
    int getColStat(const Col& col) { 
marci@1144
  1083
      return lpx_get_col_stat(lp, col_iter_map[col]); 
marci@1031
  1084
    }
marci@1031
  1085
    /// \e
marci@1031
  1086
    void printColStatus(int i) {
marci@1031
  1087
      switch (i) {
marci@1031
  1088
      case LPX_BS: cout << "LPX_BS" << endl; break;
marci@1031
  1089
      case LPX_NL: cout << "LPX_NL" << endl; break;	
marci@1031
  1090
      case LPX_NU: cout << "LPX_NU" << endl; break;
marci@1031
  1091
      case LPX_NF: cout << "LPX_NF" << endl; break;
marci@1031
  1092
      case LPX_NS: cout << "LPX_NS" << endl; break;
marci@1031
  1093
      }
marci@1031
  1094
    }
marci@1152
  1095
marci@1152
  1096
    // MIP
marci@1152
  1097
    /// \e
marci@1152
  1098
    void solveBandB() { lpx_integer(lp); }
marci@1152
  1099
    /// \e
marci@1152
  1100
    void setLP() { lpx_set_class(lp, LPX_LP); }
marci@1152
  1101
    /// \e
marci@1152
  1102
    void setMIP() { lpx_set_class(lp, LPX_MIP); }
marci@1152
  1103
  protected:
marci@1152
  1104
    /// \e
marci@1153
  1105
    void _setColCont(int i) { lpx_set_col_kind(lp, i, LPX_CV); }
marci@1152
  1106
    /// \e
marci@1153
  1107
    void _setColInt(int i) { lpx_set_col_kind(lp, i, LPX_IV); }
marci@1153
  1108
    /// \e
marci@1153
  1109
    double _getMIPPrimal(int i) { return lpx_mip_col_val(lp, i); }
marci@1031
  1110
  };
marci@1031
  1111
  
marci@1031
  1112
  /// @}
marci@1031
  1113
marci@1031
  1114
} //namespace lemon
marci@1031
  1115
marci@1152
  1116
#endif //LEMON_LP_SOLVER_BASE_H