lemon/lp_glpk.cc
author Balazs Dezso <deba@inf.elte.hu>
Tue, 02 Dec 2008 21:40:33 +0100
changeset 458 7afc121e0689
child 459 ed54c0d13df0
permissions -rw-r--r--
Port LP and MIP solvers from SVN -r3509 (#44)
deba@458
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@458
     2
 *
deba@458
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@458
     4
 *
deba@458
     5
 * Copyright (C) 2003-2008
deba@458
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@458
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@458
     8
 *
deba@458
     9
 * Permission to use, modify and distribute this software is granted
deba@458
    10
 * provided that this copyright notice appears in all copies. For
deba@458
    11
 * precise terms see the accompanying LICENSE file.
deba@458
    12
 *
deba@458
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@458
    14
 * express or implied, and with no claim as to its suitability for any
deba@458
    15
 * purpose.
deba@458
    16
 *
deba@458
    17
 */
deba@458
    18
deba@458
    19
///\file
deba@458
    20
///\brief Implementation of the LEMON-GLPK lp solver interface.
deba@458
    21
deba@458
    22
#include <lemon/lp_glpk.h>
deba@458
    23
//#include <iostream>
deba@458
    24
deba@458
    25
extern "C" {
deba@458
    26
#include <glpk.h>
deba@458
    27
}
deba@458
    28
deba@458
    29
#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
deba@458
    30
#define LEMON_glp(func) (glp_##func)
deba@458
    31
#define LEMON_lpx(func) (lpx_##func)
deba@458
    32
deba@458
    33
#define LEMON_GLP(def) (GLP_##def)
deba@458
    34
#define LEMON_LPX(def) (LPX_##def)
deba@458
    35
deba@458
    36
#else
deba@458
    37
deba@458
    38
#define LEMON_glp(func) (lpx_##func)
deba@458
    39
#define LEMON_lpx(func) (lpx_##func)
deba@458
    40
deba@458
    41
#define LEMON_GLP(def) (LPX_##def)
deba@458
    42
#define LEMON_LPX(def) (LPX_##def)
deba@458
    43
deba@458
    44
#endif
deba@458
    45
deba@458
    46
namespace lemon {
deba@458
    47
deba@458
    48
  LpGlpk::LpGlpk() : Parent() {
deba@458
    49
    solved = false;
deba@458
    50
    rows = _lp_bits::LpId(1);
deba@458
    51
    cols = _lp_bits::LpId(1);
deba@458
    52
    lp = LEMON_glp(create_prob)();
deba@458
    53
    LEMON_glp(create_index)(lp);
deba@458
    54
    messageLevel(0);
deba@458
    55
  }
deba@458
    56
deba@458
    57
  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
deba@458
    58
    solved = false;
deba@458
    59
    rows = _lp_bits::LpId(1);
deba@458
    60
    cols = _lp_bits::LpId(1);
deba@458
    61
    lp = LEMON_glp(create_prob)();
deba@458
    62
    LEMON_glp(create_index)(lp);
deba@458
    63
    messageLevel(0);
deba@458
    64
    //Coefficient matrix, row bounds
deba@458
    65
    LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
deba@458
    66
    LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
deba@458
    67
    int len;
deba@458
    68
    std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
deba@458
    69
    std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
deba@458
    70
    for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
deba@458
    71
      {
deba@458
    72
        len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
deba@458
    73
        LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
deba@458
    74
        LEMON_glp(set_row_bnds)(lp,i,
deba@458
    75
                                LEMON_glp(get_row_type)(glp.lp,i),
deba@458
    76
                                LEMON_glp(get_row_lb)(glp.lp,i),
deba@458
    77
                                LEMON_glp(get_row_ub)(glp.lp,i));
deba@458
    78
      }
deba@458
    79
deba@458
    80
    //Objective function, coloumn bounds
deba@458
    81
    LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
deba@458
    82
    //Objectif function's constant term treated separately
deba@458
    83
    LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
deba@458
    84
    for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
deba@458
    85
      {
deba@458
    86
        LEMON_glp(set_obj_coef)(lp,i,
deba@458
    87
                                LEMON_glp(get_obj_coef)(glp.lp,i));
deba@458
    88
        LEMON_glp(set_col_bnds)(lp,i,
deba@458
    89
                                LEMON_glp(get_col_type)(glp.lp,i),
deba@458
    90
                                LEMON_glp(get_col_lb)(glp.lp,i),
deba@458
    91
                                LEMON_glp(get_col_ub)(glp.lp,i));
deba@458
    92
      }
deba@458
    93
    rows = glp.rows;
deba@458
    94
    cols = glp.cols;
deba@458
    95
  }
deba@458
    96
deba@458
    97
  LpGlpk::~LpGlpk() {
deba@458
    98
    LEMON_glp(delete_prob)(lp);
deba@458
    99
  }
deba@458
   100
deba@458
   101
  int LpGlpk::_addCol() {
deba@458
   102
    int i=LEMON_glp(add_cols)(lp, 1);
deba@458
   103
    LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
deba@458
   104
    solved = false;
deba@458
   105
    return i;
deba@458
   106
  }
deba@458
   107
deba@458
   108
  ///\e
deba@458
   109
deba@458
   110
deba@458
   111
  LpSolverBase* LpGlpk::_newLp()
deba@458
   112
  {
deba@458
   113
    LpGlpk* newlp = new LpGlpk;
deba@458
   114
    return newlp;
deba@458
   115
  }
deba@458
   116
deba@458
   117
  ///\e
deba@458
   118
deba@458
   119
  LpSolverBase* LpGlpk::_copyLp()
deba@458
   120
  {
deba@458
   121
    LpGlpk *newlp = new LpGlpk(*this);
deba@458
   122
    return newlp;
deba@458
   123
  }
deba@458
   124
deba@458
   125
  int LpGlpk::_addRow() {
deba@458
   126
    int i=LEMON_glp(add_rows)(lp, 1);
deba@458
   127
    solved = false;
deba@458
   128
    return i;
deba@458
   129
  }
deba@458
   130
deba@458
   131
deba@458
   132
  void LpGlpk::_eraseCol(int i) {
deba@458
   133
    int ca[2];
deba@458
   134
    ca[1]=i;
deba@458
   135
    LEMON_glp(del_cols)(lp, 1, ca);
deba@458
   136
    solved = false;
deba@458
   137
  }
deba@458
   138
deba@458
   139
  void LpGlpk::_eraseRow(int i) {
deba@458
   140
    int ra[2];
deba@458
   141
    ra[1]=i;
deba@458
   142
    LEMON_glp(del_rows)(lp, 1, ra);
deba@458
   143
    solved = false;
deba@458
   144
  }
deba@458
   145
deba@458
   146
  void LpGlpk::_getColName(int c, std::string & name) const
deba@458
   147
  {
deba@458
   148
deba@458
   149
    const char *n = LEMON_glp(get_col_name)(lp,c);
deba@458
   150
    name = n?n:"";
deba@458
   151
  }
deba@458
   152
deba@458
   153
deba@458
   154
  void LpGlpk::_setColName(int c, const std::string & name)
deba@458
   155
  {
deba@458
   156
    LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
deba@458
   157
deba@458
   158
  }
deba@458
   159
deba@458
   160
  int LpGlpk::_colByName(const std::string& name) const
deba@458
   161
  {
deba@458
   162
    int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
deba@458
   163
    return k > 0 ? k : -1;
deba@458
   164
  }
deba@458
   165
deba@458
   166
deba@458
   167
  void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
deba@458
   168
  {
deba@458
   169
    std::vector<int> indices;
deba@458
   170
    std::vector<Value> values;
deba@458
   171
deba@458
   172
    indices.push_back(0);
deba@458
   173
    values.push_back(0);
deba@458
   174
deba@458
   175
    for(ConstRowIterator it=b; it!=e; ++it) {
deba@458
   176
      indices.push_back(it->first);
deba@458
   177
      values.push_back(it->second);
deba@458
   178
    }
deba@458
   179
deba@458
   180
    LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
deba@458
   181
                                &indices[0], &values[0]);
deba@458
   182
deba@458
   183
    solved = false;
deba@458
   184
  }
deba@458
   185
deba@458
   186
  void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
deba@458
   187
  {
deba@458
   188
    int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
deba@458
   189
deba@458
   190
    std::vector<int> indices(length + 1);
deba@458
   191
    std::vector<Value> values(length + 1);
deba@458
   192
deba@458
   193
    LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
deba@458
   194
deba@458
   195
    for (int i = 1; i <= length; ++i) {
deba@458
   196
      *b = std::make_pair(indices[i], values[i]);
deba@458
   197
      ++b;
deba@458
   198
    }
deba@458
   199
  }
deba@458
   200
deba@458
   201
  void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
deba@458
   202
deba@458
   203
    std::vector<int> indices;
deba@458
   204
    std::vector<Value> values;
deba@458
   205
deba@458
   206
    indices.push_back(0);
deba@458
   207
    values.push_back(0);
deba@458
   208
deba@458
   209
    for(ConstColIterator it=b; it!=e; ++it) {
deba@458
   210
      indices.push_back(it->first);
deba@458
   211
      values.push_back(it->second);
deba@458
   212
    }
deba@458
   213
deba@458
   214
    LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
deba@458
   215
                                &indices[0], &values[0]);
deba@458
   216
deba@458
   217
    solved = false;
deba@458
   218
  }
deba@458
   219
deba@458
   220
  void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
deba@458
   221
  {
deba@458
   222
    int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
deba@458
   223
deba@458
   224
    std::vector<int> indices(length + 1);
deba@458
   225
    std::vector<Value> values(length + 1);
deba@458
   226
deba@458
   227
    LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
deba@458
   228
deba@458
   229
    for (int i = 1; i <= length; ++i) {
deba@458
   230
      *b = std::make_pair(indices[i], values[i]);
deba@458
   231
      ++b;
deba@458
   232
    }
deba@458
   233
  }
deba@458
   234
deba@458
   235
  void LpGlpk::_setCoeff(int ix, int jx, Value value)
deba@458
   236
  {
deba@458
   237
deba@458
   238
    if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
deba@458
   239
deba@458
   240
      int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
deba@458
   241
deba@458
   242
      std::vector<int> indices(length + 2);
deba@458
   243
      std::vector<Value> values(length + 2);
deba@458
   244
deba@458
   245
      LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
deba@458
   246
deba@458
   247
      //The following code does not suppose that the elements of the
deba@458
   248
      //array indices are sorted
deba@458
   249
      bool found=false;
deba@458
   250
      for (int i = 1; i <= length; ++i) {
deba@458
   251
        if (indices[i]==jx){
deba@458
   252
          found=true;
deba@458
   253
          values[i]=value;
deba@458
   254
          break;
deba@458
   255
        }
deba@458
   256
      }
deba@458
   257
      if (!found){
deba@458
   258
        ++length;
deba@458
   259
        indices[length]=jx;
deba@458
   260
        values[length]=value;
deba@458
   261
      }
deba@458
   262
deba@458
   263
      LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
deba@458
   264
deba@458
   265
    } else {
deba@458
   266
deba@458
   267
      int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
deba@458
   268
deba@458
   269
      std::vector<int> indices(length + 2);
deba@458
   270
      std::vector<Value> values(length + 2);
deba@458
   271
deba@458
   272
      LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
deba@458
   273
deba@458
   274
      //The following code does not suppose that the elements of the
deba@458
   275
      //array indices are sorted
deba@458
   276
      bool found=false;
deba@458
   277
      for (int i = 1; i <= length; ++i) {
deba@458
   278
        if (indices[i]==ix){
deba@458
   279
          found=true;
deba@458
   280
          values[i]=value;
deba@458
   281
          break;
deba@458
   282
        }
deba@458
   283
      }
deba@458
   284
      if (!found){
deba@458
   285
        ++length;
deba@458
   286
        indices[length]=ix;
deba@458
   287
        values[length]=value;
deba@458
   288
      }
deba@458
   289
deba@458
   290
      LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
deba@458
   291
    }
deba@458
   292
deba@458
   293
    solved = false;
deba@458
   294
  }
deba@458
   295
deba@458
   296
  LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
deba@458
   297
  {
deba@458
   298
deba@458
   299
    int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
deba@458
   300
deba@458
   301
    std::vector<int> indices(length + 1);
deba@458
   302
    std::vector<Value> values(length + 1);
deba@458
   303
deba@458
   304
    LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
deba@458
   305
deba@458
   306
    //The following code does not suppose that the elements of the
deba@458
   307
    //array indices are sorted
deba@458
   308
    for (int i = 1; i <= length; ++i) {
deba@458
   309
      if (indices[i]==jx){
deba@458
   310
        return values[i];
deba@458
   311
      }
deba@458
   312
    }
deba@458
   313
    return 0;
deba@458
   314
deba@458
   315
  }
deba@458
   316
deba@458
   317
deba@458
   318
  void LpGlpk::_setColLowerBound(int i, Value lo)
deba@458
   319
  {
deba@458
   320
    if (lo==INF) {
deba@458
   321
      //FIXME error
deba@458
   322
    }
deba@458
   323
    int b=LEMON_glp(get_col_type)(lp, i);
deba@458
   324
    double up=LEMON_glp(get_col_ub)(lp, i);
deba@458
   325
    if (lo==-INF) {
deba@458
   326
      switch (b) {
deba@458
   327
      case LEMON_GLP(FR):
deba@458
   328
      case LEMON_GLP(LO):
deba@458
   329
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
deba@458
   330
        break;
deba@458
   331
      case LEMON_GLP(UP):
deba@458
   332
        break;
deba@458
   333
      case LEMON_GLP(DB):
deba@458
   334
      case LEMON_GLP(FX):
deba@458
   335
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
deba@458
   336
        break;
deba@458
   337
      default: ;
deba@458
   338
        //FIXME error
deba@458
   339
      }
deba@458
   340
    } else {
deba@458
   341
      switch (b) {
deba@458
   342
      case LEMON_GLP(FR):
deba@458
   343
      case LEMON_GLP(LO):
deba@458
   344
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
deba@458
   345
        break;
deba@458
   346
      case LEMON_GLP(UP):
deba@458
   347
      case LEMON_GLP(DB):
deba@458
   348
      case LEMON_GLP(FX):
deba@458
   349
        if (lo==up)
deba@458
   350
          LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
deba@458
   351
        else
deba@458
   352
          LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
deba@458
   353
        break;
deba@458
   354
      default: ;
deba@458
   355
        //FIXME error
deba@458
   356
      }
deba@458
   357
    }
deba@458
   358
deba@458
   359
    solved = false;
deba@458
   360
  }
deba@458
   361
deba@458
   362
  LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
deba@458
   363
  {
deba@458
   364
    int b=LEMON_glp(get_col_type)(lp, i);
deba@458
   365
      switch (b) {
deba@458
   366
      case LEMON_GLP(LO):
deba@458
   367
      case LEMON_GLP(DB):
deba@458
   368
      case LEMON_GLP(FX):
deba@458
   369
        return LEMON_glp(get_col_lb)(lp, i);
deba@458
   370
      default: ;
deba@458
   371
        return -INF;
deba@458
   372
      }
deba@458
   373
  }
deba@458
   374
deba@458
   375
  void LpGlpk::_setColUpperBound(int i, Value up)
deba@458
   376
  {
deba@458
   377
    if (up==-INF) {
deba@458
   378
      //FIXME error
deba@458
   379
    }
deba@458
   380
    int b=LEMON_glp(get_col_type)(lp, i);
deba@458
   381
    double lo=LEMON_glp(get_col_lb)(lp, i);
deba@458
   382
    if (up==INF) {
deba@458
   383
      switch (b) {
deba@458
   384
      case LEMON_GLP(FR):
deba@458
   385
      case LEMON_GLP(LO):
deba@458
   386
        break;
deba@458
   387
      case LEMON_GLP(UP):
deba@458
   388
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
deba@458
   389
        break;
deba@458
   390
      case LEMON_GLP(DB):
deba@458
   391
      case LEMON_GLP(FX):
deba@458
   392
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
deba@458
   393
        break;
deba@458
   394
      default: ;
deba@458
   395
        //FIXME error
deba@458
   396
      }
deba@458
   397
    } else {
deba@458
   398
      switch (b) {
deba@458
   399
      case LEMON_GLP(FR):
deba@458
   400
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
deba@458
   401
        break;
deba@458
   402
      case LEMON_GLP(UP):
deba@458
   403
        LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
deba@458
   404
        break;
deba@458
   405
      case LEMON_GLP(LO):
deba@458
   406
      case LEMON_GLP(DB):
deba@458
   407
      case LEMON_GLP(FX):
deba@458
   408
        if (lo==up)
deba@458
   409
          LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
deba@458
   410
        else
deba@458
   411
          LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
deba@458
   412
        break;
deba@458
   413
      default: ;
deba@458
   414
        //FIXME error
deba@458
   415
      }
deba@458
   416
    }
deba@458
   417
deba@458
   418
    solved = false;
deba@458
   419
  }
deba@458
   420
deba@458
   421
  LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
deba@458
   422
  {
deba@458
   423
    int b=LEMON_glp(get_col_type)(lp, i);
deba@458
   424
      switch (b) {
deba@458
   425
      case LEMON_GLP(UP):
deba@458
   426
      case LEMON_GLP(DB):
deba@458
   427
      case LEMON_GLP(FX):
deba@458
   428
        return LEMON_glp(get_col_ub)(lp, i);
deba@458
   429
      default: ;
deba@458
   430
        return INF;
deba@458
   431
      }
deba@458
   432
  }
deba@458
   433
deba@458
   434
  void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
deba@458
   435
  {
deba@458
   436
    //Bad parameter
deba@458
   437
    if (lb==INF || ub==-INF) {
deba@458
   438
      //FIXME error
deba@458
   439
    }
deba@458
   440
deba@458
   441
    if (lb == -INF){
deba@458
   442
      if (ub == INF){
deba@458
   443
        LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
deba@458
   444
      }
deba@458
   445
      else{
deba@458
   446
        LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
deba@458
   447
      }
deba@458
   448
    }
deba@458
   449
    else{
deba@458
   450
      if (ub==INF){
deba@458
   451
        LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
deba@458
   452
deba@458
   453
      }
deba@458
   454
      else{
deba@458
   455
        if (lb == ub){
deba@458
   456
          LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
deba@458
   457
        }
deba@458
   458
        else{
deba@458
   459
          LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
deba@458
   460
        }
deba@458
   461
      }
deba@458
   462
    }
deba@458
   463
deba@458
   464
    solved = false;
deba@458
   465
  }
deba@458
   466
deba@458
   467
  void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
deba@458
   468
  {
deba@458
   469
deba@458
   470
    int b=LEMON_glp(get_row_type)(lp, i);
deba@458
   471
    switch (b) {
deba@458
   472
    case LEMON_GLP(FR):
deba@458
   473
    case LEMON_GLP(UP):
deba@458
   474
      lb = -INF;
deba@458
   475
        break;
deba@458
   476
    default:
deba@458
   477
      lb=LEMON_glp(get_row_lb)(lp, i);
deba@458
   478
    }
deba@458
   479
deba@458
   480
    switch (b) {
deba@458
   481
    case LEMON_GLP(FR):
deba@458
   482
    case LEMON_GLP(LO):
deba@458
   483
      ub = INF;
deba@458
   484
        break;
deba@458
   485
    default:
deba@458
   486
      ub=LEMON_glp(get_row_ub)(lp, i);
deba@458
   487
    }
deba@458
   488
deba@458
   489
  }
deba@458
   490
deba@458
   491
  void LpGlpk::_setObjCoeff(int i, Value obj_coef)
deba@458
   492
  {
deba@458
   493
    //i=0 means the constant term (shift)
deba@458
   494
    LEMON_glp(set_obj_coef)(lp, i, obj_coef);
deba@458
   495
deba@458
   496
    solved = false;
deba@458
   497
  }
deba@458
   498
deba@458
   499
  LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
deba@458
   500
    //i=0 means the constant term (shift)
deba@458
   501
    return LEMON_glp(get_obj_coef)(lp, i);
deba@458
   502
  }
deba@458
   503
deba@458
   504
  void LpGlpk::_clearObj()
deba@458
   505
  {
deba@458
   506
    for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
deba@458
   507
      LEMON_glp(set_obj_coef)(lp, i, 0);
deba@458
   508
    }
deba@458
   509
deba@458
   510
    solved = false;
deba@458
   511
  }
deba@458
   512
deba@458
   513
  LpGlpk::SolveExitStatus LpGlpk::_solve()
deba@458
   514
  {
deba@458
   515
    // A way to check the problem to be solved
deba@458
   516
    //LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
deba@458
   517
deba@458
   518
    LEMON_lpx(std_basis)(lp);
deba@458
   519
    int i =  LEMON_lpx(simplex)(lp);
deba@458
   520
deba@458
   521
    switch (i) {
deba@458
   522
    case LEMON_LPX(E_OK):
deba@458
   523
      solved = true;
deba@458
   524
      return SOLVED;
deba@458
   525
    default:
deba@458
   526
      return UNSOLVED;
deba@458
   527
    }
deba@458
   528
  }
deba@458
   529
deba@458
   530
  LpGlpk::Value LpGlpk::_getPrimal(int i) const
deba@458
   531
  {
deba@458
   532
    return LEMON_glp(get_col_prim)(lp,i);
deba@458
   533
  }
deba@458
   534
deba@458
   535
  LpGlpk::Value LpGlpk::_getDual(int i) const
deba@458
   536
  {
deba@458
   537
    return LEMON_glp(get_row_dual)(lp,i);
deba@458
   538
  }
deba@458
   539
deba@458
   540
  LpGlpk::Value LpGlpk::_getPrimalValue() const
deba@458
   541
  {
deba@458
   542
    return LEMON_glp(get_obj_val)(lp);
deba@458
   543
  }
deba@458
   544
  bool LpGlpk::_isBasicCol(int i) const
deba@458
   545
  {
deba@458
   546
    return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
deba@458
   547
  }
deba@458
   548
deba@458
   549
deba@458
   550
  LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
deba@458
   551
  {
deba@458
   552
    if (!solved) return UNDEFINED;
deba@458
   553
    int stat=  LEMON_lpx(get_status)(lp);
deba@458
   554
    switch (stat) {
deba@458
   555
    case LEMON_LPX(UNDEF)://Undefined (no solve has been run yet)
deba@458
   556
      return UNDEFINED;
deba@458
   557
    case LEMON_LPX(NOFEAS)://There is no feasible solution (primal, I guess)
deba@458
   558
    case LEMON_LPX(INFEAS)://Infeasible
deba@458
   559
      return INFEASIBLE;
deba@458
   560
    case LEMON_LPX(UNBND)://Unbounded
deba@458
   561
      return INFINITE;
deba@458
   562
    case LEMON_LPX(FEAS)://Feasible
deba@458
   563
      return FEASIBLE;
deba@458
   564
    case LEMON_LPX(OPT)://Feasible
deba@458
   565
      return OPTIMAL;
deba@458
   566
    default:
deba@458
   567
      return UNDEFINED; //to avoid gcc warning
deba@458
   568
      //FIXME error
deba@458
   569
    }
deba@458
   570
  }
deba@458
   571
deba@458
   572
  LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
deba@458
   573
  {
deba@458
   574
    if (!solved) return UNDEFINED;
deba@458
   575
    switch (LEMON_lpx(get_dual_stat)(lp)) {
deba@458
   576
    case LEMON_LPX(D_UNDEF)://Undefined (no solve has been run yet)
deba@458
   577
      return UNDEFINED;
deba@458
   578
    case LEMON_LPX(D_NOFEAS)://There is no dual feasible solution
deba@458
   579
//    case LEMON_LPX(D_INFEAS://Infeasible
deba@458
   580
      return INFEASIBLE;
deba@458
   581
    case LEMON_LPX(D_FEAS)://Feasible
deba@458
   582
      switch (LEMON_lpx(get_status)(lp)) {
deba@458
   583
      case LEMON_LPX(NOFEAS):
deba@458
   584
        return INFINITE;
deba@458
   585
      case LEMON_LPX(OPT):
deba@458
   586
        return OPTIMAL;
deba@458
   587
      default:
deba@458
   588
        return FEASIBLE;
deba@458
   589
      }
deba@458
   590
    default:
deba@458
   591
      return UNDEFINED; //to avoid gcc warning
deba@458
   592
      //FIXME error
deba@458
   593
    }
deba@458
   594
  }
deba@458
   595
deba@458
   596
  LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
deba@458
   597
  {
deba@458
   598
    if (!solved) return UNKNOWN;
deba@458
   599
      //int stat=  LEMON_glp(get_status(lp);
deba@458
   600
    int statp=  LEMON_lpx(get_prim_stat)(lp);
deba@458
   601
    int statd=  LEMON_lpx(get_dual_stat)(lp);
deba@458
   602
    if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
deba@458
   603
        return PRIMAL_DUAL_FEASIBLE;
deba@458
   604
    if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
deba@458
   605
        return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
deba@458
   606
    if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
deba@458
   607
        return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
deba@458
   608
    if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
deba@458
   609
        return PRIMAL_DUAL_INFEASIBLE;
deba@458
   610
    //In all other cases
deba@458
   611
    return UNKNOWN;
deba@458
   612
  }
deba@458
   613
deba@458
   614
  void LpGlpk::_setMax()
deba@458
   615
  {
deba@458
   616
    solved = false;
deba@458
   617
    LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
deba@458
   618
  }
deba@458
   619
deba@458
   620
  void LpGlpk::_setMin()
deba@458
   621
  {
deba@458
   622
    solved = false;
deba@458
   623
    LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
deba@458
   624
  }
deba@458
   625
deba@458
   626
  bool LpGlpk::_isMax() const
deba@458
   627
  {
deba@458
   628
    return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
deba@458
   629
  }
deba@458
   630
deba@458
   631
deba@458
   632
deba@458
   633
  void LpGlpk::messageLevel(int m)
deba@458
   634
  {
deba@458
   635
    LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
deba@458
   636
  }
deba@458
   637
deba@458
   638
  void LpGlpk::presolver(bool b)
deba@458
   639
  {
deba@458
   640
    LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
deba@458
   641
  }
deba@458
   642
deba@458
   643
deba@458
   644
} //END OF NAMESPACE LEMON