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