src/work/marci/lp/lp_solver_wrapper.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 765 4405b6be83bb
child 888 cc3590763f7f
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
marci@764
     1
// -*- c++ -*-
marci@764
     2
#ifndef HUGO_LP_SOLVER_WRAPPER_H
marci@764
     3
#define HUGO_LP_SOLVER_WRAPPER
marci@764
     4
alpar@765
     5
///\ingroup misc
alpar@765
     6
///\file
alpar@765
     7
///\brief Dijkstra algorithm.
alpar@765
     8
marci@764
     9
// #include <stdio.h>
marci@764
    10
#include <stdlib.h>
marci@764
    11
// #include <stdio>
marci@764
    12
//#include <stdlib>
marci@764
    13
#include "glpk.h"
marci@764
    14
marci@764
    15
#include <iostream>
marci@764
    16
#include <vector>
marci@764
    17
#include <string>
marci@764
    18
#include <list>
marci@764
    19
#include <memory>
marci@764
    20
#include <utility>
marci@764
    21
marci@764
    22
//#include <sage_graph.h>
marci@764
    23
//#include <hugo/list_graph.h>
marci@764
    24
//#include <hugo/graph_wrapper.h>
marci@764
    25
#include <hugo/invalid.h>
marci@764
    26
//#include <bfs_dfs.h>
marci@764
    27
//#include <stp.h>
marci@764
    28
//#include <hugo/max_flow.h>
marci@764
    29
//#include <augmenting_flow.h>
marci@764
    30
//#include <iter_map.h>
marci@764
    31
marci@764
    32
using std::cout;
marci@764
    33
using std::cin;
marci@764
    34
using std::endl;
marci@764
    35
marci@764
    36
namespace hugo {
marci@764
    37
alpar@765
    38
  
alpar@765
    39
  /// \addtogroup misc
alpar@765
    40
  /// @{
alpar@765
    41
marci@764
    42
  /// \brief A partitioned vector with iterable classes.
marci@764
    43
  ///
marci@764
    44
  /// This class implements a container in which the data is stored in an 
marci@764
    45
  /// stl vector, the range is partitioned into sets and each set is 
marci@764
    46
  /// doubly linked in a list. 
marci@764
    47
  /// That is, each class is iterable by hugo iterators, and any member of 
marci@764
    48
  /// the vector can bo moved to an other class.
marci@764
    49
  template <typename T>
marci@764
    50
  class IterablePartition {
marci@764
    51
  protected:
marci@764
    52
    struct Node {
marci@764
    53
      T data;
marci@764
    54
      int prev; //invalid az -1
marci@764
    55
      int next; 
marci@764
    56
    };
marci@764
    57
    std::vector<Node> nodes;
marci@764
    58
    struct Tip {
marci@764
    59
      int first;
marci@764
    60
      int last;
marci@764
    61
    };
marci@764
    62
    std::vector<Tip> tips;
marci@764
    63
  public:
marci@764
    64
    /// The classes are indexed by integers from \c 0 to \c classNum()-1.
marci@764
    65
    int classNum() const { return tips.size(); }
marci@764
    66
    /// This hugo style iterator iterates through a class. 
marci@764
    67
    class ClassIt;
marci@764
    68
    /// Constructor. The number of classes is to be given which is fixed 
marci@764
    69
    /// over the life of the container. 
marci@764
    70
    /// The partition classes are indexed from 0 to class_num-1. 
marci@764
    71
    IterablePartition(int class_num) { 
marci@764
    72
      for (int i=0; i<class_num; ++i) {
marci@764
    73
	Tip t;
marci@764
    74
	t.first=t.last=-1;
marci@764
    75
	tips.push_back(t);
marci@764
    76
      }
marci@764
    77
    }
marci@764
    78
  protected:
marci@764
    79
    void befuz(ClassIt it, int class_id) {
marci@764
    80
      if (tips[class_id].first==-1) {
marci@764
    81
	if (tips[class_id].last==-1) {
marci@764
    82
	  nodes[it.i].prev=nodes[it.i].next=-1;
marci@764
    83
	  tips[class_id].first=tips[class_id].last=it.i;
marci@764
    84
	}
marci@764
    85
      } else {
marci@764
    86
	nodes[it.i].prev=tips[class_id].last;
marci@764
    87
	nodes[it.i].next=-1;
marci@764
    88
	nodes[tips[class_id].last].next=it.i;
marci@764
    89
	tips[class_id].last=it.i;
marci@764
    90
      }
marci@764
    91
    }
marci@764
    92
    void kifuz(ClassIt it, int class_id) {
marci@764
    93
      if (tips[class_id].first==it.i) {
marci@764
    94
	if (tips[class_id].last==it.i) {
marci@764
    95
	  tips[class_id].first=tips[class_id].last=-1;
marci@764
    96
	} else {
marci@764
    97
	  tips[class_id].first=nodes[it.i].next;
marci@764
    98
	  nodes[nodes[it.i].next].prev=-1;
marci@764
    99
	}
marci@764
   100
      } else {
marci@764
   101
	if (tips[class_id].last==it.i) {
marci@764
   102
	  tips[class_id].last=nodes[it.i].prev;
marci@764
   103
	  nodes[nodes[it.i].prev].next=-1;
marci@764
   104
	} else {
marci@764
   105
	  nodes[nodes[it.i].next].prev=nodes[it.i].prev;
marci@764
   106
	  nodes[nodes[it.i].prev].next=nodes[it.i].next;
marci@764
   107
	}
marci@764
   108
      }
marci@764
   109
    }
marci@764
   110
  public:
marci@764
   111
    /// A new element with data \c t is pushed into the vector and into class 
marci@764
   112
    /// \c class_id.
marci@764
   113
    ClassIt push_back(const T& t, int class_id) { 
marci@764
   114
      Node n;
marci@764
   115
      n.data=t;
marci@764
   116
      nodes.push_back(n);
marci@764
   117
      int i=nodes.size()-1;
marci@764
   118
      befuz(i, class_id);
marci@764
   119
      return i;
marci@764
   120
    }
marci@764
   121
    /// A member is moved to an other class.
marci@764
   122
    void set(ClassIt it, int old_class_id, int new_class_id) {
marci@764
   123
      kifuz(it.i, old_class_id);
marci@764
   124
      befuz(it.i, new_class_id);
marci@764
   125
    }
marci@764
   126
    /// Returns the data pointed by \c it.
marci@764
   127
    T& operator[](ClassIt it) { return nodes[it.i].data; }
marci@764
   128
    /// Returns the data pointed by \c it.
marci@764
   129
    const T& operator[](ClassIt it) const { return nodes[it.i].data; }
alpar@765
   130
    ///.
marci@764
   131
    class ClassIt {
marci@764
   132
      friend class IterablePartition;
marci@764
   133
    protected:
marci@764
   134
      int i;
marci@764
   135
    public:
marci@764
   136
      /// Default constructor.
marci@764
   137
      ClassIt() { }
marci@764
   138
      /// This constructor constructs an iterator which points
marci@764
   139
      /// to the member of th container indexed by the integer _i.
marci@764
   140
      ClassIt(const int& _i) : i(_i) { }
marci@764
   141
      /// Invalid constructor.
marci@764
   142
      ClassIt(const Invalid&) : i(-1) { }
marci@764
   143
    };
marci@764
   144
    /// First member of class \c class_id.
marci@764
   145
    ClassIt& first(ClassIt& it, int class_id) const {
marci@764
   146
      it.i=tips[class_id].first;
marci@764
   147
      return it;
marci@764
   148
    }
marci@764
   149
    /// Next member.
marci@764
   150
    ClassIt& next(ClassIt& it) const {
marci@764
   151
      it.i=nodes[it.i].next;
marci@764
   152
      return it;
marci@764
   153
    }
marci@764
   154
    /// True iff the iterator is valid.
marci@764
   155
    bool valid(const ClassIt& it) const { return it.i!=-1; }
marci@764
   156
  };
marci@764
   157
  
marci@764
   158
  /// \brief Wrappers for LP solvers
marci@764
   159
  /// 
marci@764
   160
  /// This class implements a hugo wrapper for glpk.
marci@764
   161
  /// Later other LP-solvers will be wrapped into hugo.
marci@764
   162
  /// The aim of this class is to give a general surface to different 
marci@764
   163
  /// solvers, i.e. it makes possible to write algorithms using LP's, 
marci@764
   164
  /// in which the solver can be changed to an other one easily.
marci@764
   165
  class LPSolverWrapper {
marci@764
   166
  public:
marci@764
   167
marci@764
   168
//   class Row {
marci@764
   169
//   protected:
marci@764
   170
//     int i;
marci@764
   171
//   public:
marci@764
   172
//     Row() { }
marci@764
   173
//     Row(const Invalid&) : i(0) { }
marci@764
   174
//     Row(const int& _i) : i(_i) { }
marci@764
   175
//     operator int() const { return i; }
marci@764
   176
//   };
marci@764
   177
//   class RowIt : public Row {
marci@764
   178
//   public:
marci@764
   179
//     RowIt(const Row& row) : Row(row) { }
marci@764
   180
//   };
marci@764
   181
marci@764
   182
//   class Col {
marci@764
   183
//   protected:
marci@764
   184
//     int i;
marci@764
   185
//   public:
marci@764
   186
//     Col() { }
marci@764
   187
//     Col(const Invalid&) : i(0) { }
marci@764
   188
//     Col(const int& _i) : i(_i) { }
marci@764
   189
//     operator int() const { return i; }
marci@764
   190
//   };
marci@764
   191
//   class ColIt : public Col {
marci@764
   192
//     ColIt(const Col& col) : Col(col) { }
marci@764
   193
//   };
marci@764
   194
marci@764
   195
  public:
alpar@765
   196
    ///.
marci@764
   197
    LPX* lp;
alpar@765
   198
    ///.
marci@764
   199
    typedef IterablePartition<int>::ClassIt RowIt;
alpar@765
   200
    ///.
marci@764
   201
    IterablePartition<int> row_iter_map;
alpar@765
   202
    ///.
marci@764
   203
    typedef IterablePartition<int>::ClassIt ColIt;
alpar@765
   204
    ///.
marci@764
   205
    IterablePartition<int> col_iter_map;
marci@764
   206
    //std::vector<int> row_id_to_lp_row_id;
marci@764
   207
    //std::vector<int> col_id_to_lp_col_id;
alpar@765
   208
    ///.
marci@764
   209
    const int VALID_ID;
alpar@765
   210
    ///.
marci@764
   211
    const int INVALID_ID;
marci@764
   212
marci@764
   213
  public:
alpar@765
   214
    ///.
marci@764
   215
    LPSolverWrapper() : lp(lpx_create_prob()), 
marci@764
   216
			row_iter_map(2), 
marci@764
   217
			col_iter_map(2), 
marci@764
   218
			//row_id_to_lp_row_id(), col_id_to_lp_col_id(), 
marci@764
   219
			VALID_ID(0), INVALID_ID(1) {
marci@764
   220
      lpx_set_int_parm(lp, LPX_K_DUAL, 1);
marci@764
   221
    }
alpar@765
   222
    ///.
marci@764
   223
    ~LPSolverWrapper() {
marci@764
   224
      lpx_delete_prob(lp);
marci@764
   225
    }
alpar@765
   226
    ///.
marci@764
   227
    void setMinimize() { 
marci@764
   228
      lpx_set_obj_dir(lp, LPX_MIN);
marci@764
   229
    }
alpar@765
   230
    ///.
marci@764
   231
    void setMaximize() { 
marci@764
   232
      lpx_set_obj_dir(lp, LPX_MAX);
marci@764
   233
    }
alpar@765
   234
    ///.
marci@764
   235
    ColIt addCol() {
marci@764
   236
      int i=lpx_add_cols(lp, 1);  
marci@764
   237
      ColIt col_it;
marci@764
   238
      col_iter_map.first(col_it, INVALID_ID);
marci@764
   239
      if (col_iter_map.valid(col_it)) { //van hasznalhato hely
marci@764
   240
	col_iter_map.set(col_it, INVALID_ID, VALID_ID);
marci@764
   241
	col_iter_map[col_it]=i;
marci@764
   242
	//col_id_to_lp_col_id[col_iter_map[col_it]]=i;
marci@764
   243
      } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@764
   244
	//col_id_to_lp_col_id.push_back(i);
marci@764
   245
	//int j=col_id_to_lp_col_id.size()-1;
marci@764
   246
	col_it=col_iter_map.push_back(i, VALID_ID);
marci@764
   247
      }
marci@764
   248
//    edge_index_map.set(e, i);
marci@764
   249
//    lpx_set_col_bnds(lp, i, LPX_DB, 0.0, 1.0);
marci@764
   250
//    lpx_set_obj_coef(lp, i, cost[e]);    
marci@764
   251
      return col_it;
marci@764
   252
    }
alpar@765
   253
    ///.
marci@764
   254
    RowIt addRow() {
marci@764
   255
      int i=lpx_add_rows(lp, 1);  
marci@764
   256
      RowIt row_it;
marci@764
   257
      row_iter_map.first(row_it, INVALID_ID);
marci@764
   258
      if (row_iter_map.valid(row_it)) { //van hasznalhato hely
marci@764
   259
	row_iter_map.set(row_it, INVALID_ID, VALID_ID);
marci@764
   260
	row_iter_map[row_it]=i;
marci@764
   261
      } else { //a cucc vegere kell inzertalni mert nincs szabad hely
marci@764
   262
	row_it=row_iter_map.push_back(i, VALID_ID);
marci@764
   263
      }
marci@764
   264
      return row_it;
marci@764
   265
    }
marci@764
   266
    //pair<RowIt, double>-bol kell megadni egy std range-et
alpar@765
   267
    ///.
marci@764
   268
    template <typename Begin, typename End>
marci@764
   269
    void setColCoeffs(const ColIt& col_it, 
marci@764
   270
		      Begin begin, End end) {
marci@764
   271
      int mem_length=1+lpx_get_num_rows(lp);
marci@764
   272
      int* indices = new int[mem_length];
marci@764
   273
      double* doubles = new double[mem_length];
marci@764
   274
      int length=0;
marci@764
   275
      for ( ; begin!=end; ++begin) {
marci@764
   276
	++length;
marci@764
   277
	indices[length]=row_iter_map[begin->first];
marci@764
   278
	doubles[length]=begin->second;
marci@764
   279
      }
marci@764
   280
      lpx_set_mat_col(lp, col_iter_map[col_it], length, indices, doubles);
marci@764
   281
      delete [] indices;
marci@764
   282
      delete [] doubles;
marci@764
   283
    }
marci@764
   284
    //pair<ColIt, double>-bol kell megadni egy std range-et
alpar@765
   285
    ///.
marci@764
   286
    template <typename Begin, typename End>
marci@764
   287
    void setRowCoeffs(const RowIt& row_it, 
marci@764
   288
		      Begin begin, End end) {
marci@764
   289
      int mem_length=1+lpx_get_num_cols(lp);
marci@764
   290
      int* indices = new int[mem_length];
marci@764
   291
      double* doubles = new double[mem_length];
marci@764
   292
      int length=0;
marci@764
   293
      for ( ; begin!=end; ++begin) {
marci@764
   294
	++length;
marci@764
   295
	indices[length]=col_iter_map[begin->first];
marci@764
   296
	doubles[length]=begin->second;
marci@764
   297
      }
marci@764
   298
      lpx_set_mat_row(lp, row_iter_map[row_it], length, indices, doubles);
marci@764
   299
      delete [] indices;
marci@764
   300
      delete [] doubles;
marci@764
   301
    }
alpar@765
   302
    ///.
marci@764
   303
    void eraseCol(const ColIt& col_it) {
marci@764
   304
      col_iter_map.set(col_it, VALID_ID, INVALID_ID);
marci@764
   305
      int cols[2];
marci@764
   306
      cols[1]=col_iter_map[col_it];
marci@764
   307
      lpx_del_cols(lp, 1, cols);
marci@764
   308
      col_iter_map[col_it]=0; //glpk specifikus
marci@764
   309
      ColIt it;
marci@764
   310
      for (col_iter_map.first(it, VALID_ID); 
marci@764
   311
	   col_iter_map.valid(it); col_iter_map.next(it)) {
marci@764
   312
	if (col_iter_map[it]>cols[1]) --col_iter_map[it];
marci@764
   313
      }
marci@764
   314
    }
alpar@765
   315
    ///.
marci@764
   316
    void eraseRow(const RowIt& row_it) {
marci@764
   317
      row_iter_map.set(row_it, VALID_ID, INVALID_ID);
marci@764
   318
      int rows[2];
marci@764
   319
      rows[1]=row_iter_map[row_it];
marci@764
   320
      lpx_del_rows(lp, 1, rows);
marci@764
   321
      row_iter_map[row_it]=0; //glpk specifikus
marci@764
   322
      RowIt it;
marci@764
   323
      for (row_iter_map.first(it, VALID_ID); 
marci@764
   324
	   row_iter_map.valid(it); row_iter_map.next(it)) {
marci@764
   325
	if (row_iter_map[it]>rows[1]) --row_iter_map[it];
marci@764
   326
      }
marci@764
   327
    }
alpar@765
   328
    ///.
marci@764
   329
    void setColBounds(const ColIt& col_it, int bound_type, 
marci@764
   330
		      double lo, double up) {
marci@764
   331
      lpx_set_col_bnds(lp, col_iter_map[col_it], bound_type, lo, up);
marci@764
   332
    }
alpar@765
   333
    ///.
marci@768
   334
    double getObjCoef(const ColIt& col_it) { 
marci@768
   335
      return lpx_get_obj_coef(lp, col_iter_map[col_it]);
marci@764
   336
    }
alpar@765
   337
    ///.
marci@764
   338
    void setRowBounds(const RowIt& row_it, int bound_type, 
marci@764
   339
		      double lo, double up) {
marci@764
   340
      lpx_set_row_bnds(lp, row_iter_map[row_it], bound_type, lo, up);
marci@764
   341
    }
marci@764
   342
//   void setObjCoef(const RowIt& row_it, double obj_coef) { 
marci@764
   343
//     lpx_set_obj_coef(lp, row_iter_map[row_it], obj_coef);
marci@764
   344
//   }
alpar@765
   345
    ///.
marci@764
   346
    void solveSimplex() { lpx_simplex(lp); }
alpar@765
   347
    ///.
marci@764
   348
    void solvePrimalSimplex() { lpx_simplex(lp); }
alpar@765
   349
    ///.
marci@764
   350
    void solveDualSimplex() { lpx_simplex(lp); }
alpar@765
   351
    ///.
marci@764
   352
    double getPrimal(const ColIt& col_it) {
marci@764
   353
      return lpx_get_col_prim(lp, col_iter_map[col_it]);
marci@764
   354
    }
alpar@765
   355
    ///.
marci@764
   356
    double getObjVal() { return lpx_get_obj_val(lp); }
alpar@765
   357
    ///.
marci@764
   358
    int rowNum() const { return lpx_get_num_rows(lp); }
alpar@765
   359
    ///.
marci@764
   360
    int colNum() const { return lpx_get_num_cols(lp); }
alpar@765
   361
    ///.
marci@764
   362
    int warmUp() { return lpx_warm_up(lp); }
alpar@765
   363
    ///.
marci@764
   364
    void printWarmUpStatus(int i) {
marci@764
   365
      switch (i) {
marci@764
   366
	case LPX_E_OK: cout << "LPX_E_OK" << endl; break;
marci@764
   367
	case LPX_E_EMPTY: cout << "LPX_E_EMPTY" << endl; break;	
marci@764
   368
	case LPX_E_BADB: cout << "LPX_E_BADB" << endl; break;
marci@764
   369
	case LPX_E_SING: cout << "LPX_E_SING" << endl; break;
marci@764
   370
      }
marci@764
   371
    }
alpar@765
   372
    ///.
marci@764
   373
    int getPrimalStatus() { return lpx_get_prim_stat(lp); }
alpar@765
   374
    ///.
marci@764
   375
    void printPrimalStatus(int i) {
marci@764
   376
      switch (i) {
marci@764
   377
	case LPX_P_UNDEF: cout << "LPX_P_UNDEF" << endl; break;
marci@764
   378
	case LPX_P_FEAS: cout << "LPX_P_FEAS" << endl; break;	
marci@764
   379
	case LPX_P_INFEAS: cout << "LPX_P_INFEAS" << endl; break;
marci@764
   380
	case LPX_P_NOFEAS: cout << "LPX_P_NOFEAS" << endl; break;
marci@764
   381
      }
marci@764
   382
    }
alpar@765
   383
    ///.
marci@764
   384
    int getDualStatus() { return lpx_get_dual_stat(lp); }
alpar@765
   385
    ///.
marci@764
   386
    void printDualStatus(int i) {
marci@764
   387
      switch (i) {
marci@764
   388
	case LPX_D_UNDEF: cout << "LPX_D_UNDEF" << endl; break;
marci@764
   389
	case LPX_D_FEAS: cout << "LPX_D_FEAS" << endl; break;	
marci@764
   390
	case LPX_D_INFEAS: cout << "LPX_D_INFEAS" << endl; break;
marci@764
   391
	case LPX_D_NOFEAS: cout << "LPX_D_NOFEAS" << endl; break;
marci@764
   392
      }
marci@764
   393
    }
marci@764
   394
    /// Returns the status of the slack variable assigned to row \c row_it.
marci@764
   395
    int getRowStat(const RowIt& row_it) { 
marci@764
   396
      return lpx_get_row_stat(lp, row_iter_map[row_it]); 
marci@764
   397
    }
alpar@765
   398
    ///.
marci@764
   399
    void printRowStatus(int i) {
marci@764
   400
      switch (i) {
marci@764
   401
	case LPX_BS: cout << "LPX_BS" << endl; break;
marci@764
   402
	case LPX_NL: cout << "LPX_NL" << endl; break;	
marci@764
   403
	case LPX_NU: cout << "LPX_NU" << endl; break;
marci@764
   404
	case LPX_NF: cout << "LPX_NF" << endl; break;
marci@764
   405
	case LPX_NS: cout << "LPX_NS" << endl; break;
marci@764
   406
      }
marci@764
   407
    }
marci@764
   408
    /// Returns the status of the variable assigned to column \c col_it.
marci@764
   409
    int getColStat(const ColIt& col_it) { 
marci@764
   410
      return lpx_get_col_stat(lp, col_iter_map[col_it]); 
marci@764
   411
    }
alpar@765
   412
    ///.
marci@764
   413
    void printColStatus(int i) {
marci@764
   414
      switch (i) {
marci@764
   415
	case LPX_BS: cout << "LPX_BS" << endl; break;
marci@764
   416
	case LPX_NL: cout << "LPX_NL" << endl; break;	
marci@764
   417
	case LPX_NU: cout << "LPX_NU" << endl; break;
marci@764
   418
	case LPX_NF: cout << "LPX_NF" << endl; break;
marci@764
   419
	case LPX_NS: cout << "LPX_NS" << endl; break;
marci@764
   420
      }
marci@764
   421
    }
marci@764
   422
  };
alpar@765
   423
  
alpar@765
   424
  /// @}
marci@764
   425
marci@764
   426
} //namespace hugo
marci@764
   427
marci@764
   428
#endif //HUGO_LP_SOLVER_WRAPPER_H