lemon/lp_glpk.cc
author alpar
Tue, 24 Apr 2007 09:39:01 +0000
changeset 2436 0c941c524b47
parent 2386 81b47fc5c444
child 2441 d8d6ab871608
permissions -rw-r--r--
Integer parameters also convert to double
athos@1261
     1
/* -*- C++ -*-
athos@1261
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
athos@1261
     8
 *
athos@1261
     9
 * Permission to use, modify and distribute this software is granted
athos@1261
    10
 * provided that this copyright notice appears in all copies. For
athos@1261
    11
 * precise terms see the accompanying LICENSE file.
athos@1261
    12
 *
athos@1261
    13
 * This software is provided "AS IS" with no warranty of any kind,
athos@1261
    14
 * express or implied, and with no claim as to its suitability for any
athos@1261
    15
 * purpose.
athos@1261
    16
 *
athos@1261
    17
 */
athos@1261
    18
athos@1261
    19
///\file
athos@1261
    20
///\brief Implementation of the LEMON-GLPK lp solver interface.
athos@1261
    21
ladanyi@1305
    22
#include <lemon/lp_glpk.h>
athos@1473
    23
//#include <iostream>
athos@1261
    24
namespace lemon {
athos@1261
    25
alpar@1364
    26
deba@2363
    27
  LpGlpk::LpGlpk() : Parent() {
deba@2363
    28
    rows = _lp_bits::LpId(1);
deba@2363
    29
    cols = _lp_bits::LpId(1);
deba@2363
    30
    lp = lpx_create_prob();
deba@2368
    31
    lpx_create_index(lp);
deba@2363
    32
    ///\todo control function for this:
alpar@1321
    33
    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
alpar@1321
    34
    messageLevel(0);
alpar@1321
    35
  }
alpar@1321
    36
  
deba@2363
    37
  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
deba@2363
    38
    rows = _lp_bits::LpId(1);
deba@2363
    39
    cols = _lp_bits::LpId(1);
deba@2363
    40
    lp = lpx_create_prob();
deba@2366
    41
    lpx_create_index(lp);
deba@2363
    42
    ///\todo control function for this:
alpar@2321
    43
    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
alpar@2321
    44
    messageLevel(0);
alpar@2321
    45
    //Coefficient matrix, row bounds
alpar@2321
    46
    lpx_add_rows(lp, lpx_get_num_rows(glp.lp));
alpar@2321
    47
    lpx_add_cols(lp, lpx_get_num_cols(glp.lp));
alpar@2321
    48
    int len;
alpar@2321
    49
    int ind[1+lpx_get_num_cols(glp.lp)];
alpar@2321
    50
    Value val[1+lpx_get_num_cols(glp.lp)];
alpar@2321
    51
    for (int i=1;i<=lpx_get_num_rows(glp.lp);++i)
alpar@2321
    52
      {
alpar@2321
    53
	len=lpx_get_mat_row(glp.lp,i,ind,val);
alpar@2321
    54
	lpx_set_mat_row(lp, i,len,ind,val);
alpar@2321
    55
	lpx_set_row_bnds(lp,i,lpx_get_row_type(glp.lp,i),
alpar@2321
    56
			 lpx_get_row_lb(glp.lp,i),lpx_get_row_ub(glp.lp,i));
alpar@2321
    57
      }
alpar@2321
    58
alpar@2321
    59
    //Objective function, coloumn bounds
alpar@2321
    60
    lpx_set_obj_dir(lp, lpx_get_obj_dir(glp.lp));
alpar@2321
    61
    //Objectif function's constant term treated separately
alpar@2321
    62
    lpx_set_obj_coef(lp,0,lpx_get_obj_coef(glp.lp,0));
alpar@2321
    63
    for (int i=1;i<=lpx_get_num_cols(glp.lp);++i)
alpar@2321
    64
      {
alpar@2321
    65
	lpx_set_obj_coef(lp,i,lpx_get_obj_coef(glp.lp,i));
alpar@2321
    66
	lpx_set_col_bnds(lp,i,lpx_get_col_type(glp.lp,i),
alpar@2321
    67
			 lpx_get_col_lb(glp.lp,i),lpx_get_col_ub(glp.lp,i));
alpar@2321
    68
      }
alpar@2321
    69
  }
alpar@2321
    70
  
alpar@1321
    71
  LpGlpk::~LpGlpk() {
alpar@1321
    72
    lpx_delete_prob(lp);
alpar@1321
    73
  }
alpar@1321
    74
  
alpar@1321
    75
  int LpGlpk::_addCol() { 
alpar@1321
    76
    int i=lpx_add_cols(lp, 1);
alpar@1321
    77
    _setColLowerBound(i, -INF);
alpar@1321
    78
    _setColUpperBound(i, INF);
alpar@1321
    79
    return i;
alpar@1321
    80
  }
alpar@1321
    81
athos@1436
    82
  ///\e
athos@1436
    83
athos@1436
    84
athos@1436
    85
  LpSolverBase &LpGlpk::_newLp()
athos@1436
    86
  {
alpar@2321
    87
    LpGlpk* newlp=new LpGlpk;
athos@1436
    88
    return *newlp;
athos@1436
    89
  }
athos@1436
    90
  
athos@1436
    91
  ///\e
athos@1436
    92
athos@1436
    93
  LpSolverBase &LpGlpk::_copyLp()
athos@1436
    94
  {
alpar@2321
    95
    LpGlpk* newlp=new LpGlpk(*this);
athos@1436
    96
    return *newlp;
athos@1436
    97
  }
athos@1436
    98
alpar@1321
    99
  int LpGlpk::_addRow() { 
alpar@1321
   100
    int i=lpx_add_rows(lp, 1);
alpar@1321
   101
    return i;
alpar@1321
   102
  }
alpar@1321
   103
alpar@1321
   104
  
athos@1432
   105
  void LpGlpk::_eraseCol(int i) {
deba@2386
   106
    int ca[2];
deba@2386
   107
    ca[1]=i;
deba@2386
   108
    lpx_del_cols(lp, 1, ca);
athos@1432
   109
  }
athos@1432
   110
  
athos@1432
   111
  void LpGlpk::_eraseRow(int i) {
deba@2386
   112
    int ra[2];
deba@2386
   113
    ra[1]=i;
deba@2386
   114
    lpx_del_rows(lp, 1, ra);
athos@1432
   115
  }
athos@1432
   116
deba@2386
   117
  void LpGlpk::_getColName(int c, std::string & name) const
alpar@1895
   118
  {
alpar@1895
   119
    
deba@2386
   120
    char *n = lpx_get_col_name(lp,c);
alpar@1895
   121
    name = n?n:"";
alpar@1895
   122
  }
alpar@1895
   123
  
alpar@1895
   124
  
deba@2386
   125
  void LpGlpk::_setColName(int c, const std::string & name)
alpar@1895
   126
  {
deba@2386
   127
    lpx_set_col_name(lp,c,const_cast<char*>(name.c_str()));
athos@2349
   128
alpar@1895
   129
  }
deba@2366
   130
deba@2366
   131
  int LpGlpk::_colByName(const std::string& name) const
deba@2366
   132
  {
deba@2366
   133
    int k = lpx_find_col(lp, const_cast<char*>(name.c_str()));
deba@2366
   134
    return k > 0 ? k : -1; 
deba@2366
   135
  }
deba@2366
   136
alpar@1895
   137
  
deba@2364
   138
  void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) 
alpar@1321
   139
  {
deba@2312
   140
    std::vector<int> indices;
deba@2312
   141
    std::vector<Value> values;
deba@2312
   142
deba@2312
   143
    indices.push_back(0);
deba@2312
   144
    values.push_back(0);
deba@2312
   145
deba@2364
   146
    for(ConstRowIterator it=b; it!=e; ++it) {
deba@2312
   147
      indices.push_back(it->first);
deba@2312
   148
      values.push_back(it->second);
deba@2312
   149
    }
deba@2312
   150
deba@2312
   151
    lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
alpar@1321
   152
  }
deba@2364
   153
deba@2386
   154
  void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
deba@2364
   155
  {
deba@2386
   156
    int length = lpx_get_mat_row(lp, ix, 0, 0);
deba@2364
   157
    
deba@2364
   158
    std::vector<int> indices(length + 1);
deba@2364
   159
    std::vector<Value> values(length + 1);
deba@2364
   160
    
deba@2386
   161
    lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
deba@2364
   162
    
deba@2364
   163
    for (int i = 1; i <= length; ++i) {
deba@2364
   164
      *b = std::make_pair(indices[i], values[i]);
deba@2364
   165
      ++b;
deba@2364
   166
    }
deba@2364
   167
  }
alpar@1321
   168
  
deba@2386
   169
  void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
deba@2312
   170
deba@2312
   171
    std::vector<int> indices;
deba@2312
   172
    std::vector<Value> values;
deba@2312
   173
deba@2312
   174
    indices.push_back(0);
deba@2312
   175
    values.push_back(0);
deba@2312
   176
deba@2364
   177
    for(ConstColIterator it=b; it!=e; ++it) {
deba@2312
   178
      indices.push_back(it->first);
deba@2312
   179
      values.push_back(it->second);
deba@2312
   180
    }
deba@2312
   181
    
deba@2386
   182
    lpx_set_mat_col(lp, ix, values.size() - 1, &indices[0], &values[0]);
alpar@1321
   183
  }
athos@1431
   184
deba@2386
   185
  void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
deba@2364
   186
  {
deba@2386
   187
    int length = lpx_get_mat_col(lp, ix, 0, 0);
deba@2364
   188
    
deba@2364
   189
    std::vector<int> indices(length + 1);
deba@2364
   190
    std::vector<Value> values(length + 1);
deba@2364
   191
    
deba@2386
   192
    lpx_get_mat_col(lp, ix, &indices[0], &values[0]);
deba@2364
   193
    
deba@2364
   194
    for (int i = 1; i <= length; ++i) {
deba@2364
   195
      *b = std::make_pair(indices[i], values[i]);
deba@2364
   196
      ++b;
deba@2364
   197
    }
deba@2364
   198
  }
athos@1431
   199
deba@2386
   200
  void LpGlpk::_setCoeff(int ix, int jx, Value value) 
athos@1431
   201
  {
deba@2312
   202
deba@2312
   203
    if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
deba@2312
   204
deba@2386
   205
      int length=lpx_get_mat_row(lp, ix, 0, 0);
deba@2312
   206
      
deba@2312
   207
      std::vector<int> indices(length + 2);
deba@2312
   208
      std::vector<Value> values(length + 2);
deba@2312
   209
      
deba@2386
   210
      lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
deba@2312
   211
      
deba@2312
   212
      //The following code does not suppose that the elements of the
deba@2312
   213
      //array indices are sorted
deba@2312
   214
      bool found=false;
deba@2312
   215
      for (int i = 1; i <= length; ++i) {
deba@2386
   216
        if (indices[i]==jx){
deba@2312
   217
          found=true;
deba@2312
   218
          values[i]=value;
deba@2312
   219
          break;
deba@2312
   220
        }
deba@2312
   221
      }
deba@2312
   222
      if (!found){
deba@2312
   223
        ++length;
deba@2386
   224
        indices[length]=jx;
deba@2312
   225
        values[length]=value;
deba@2312
   226
      }
athos@1431
   227
    
deba@2386
   228
      lpx_set_mat_row(lp, ix, length, &indices[0], &values[0]);
deba@2312
   229
deba@2312
   230
    } else {
deba@2312
   231
deba@2386
   232
      int length=lpx_get_mat_col(lp, jx, 0, 0);
deba@2312
   233
      
deba@2312
   234
      std::vector<int> indices(length + 2);
deba@2312
   235
      std::vector<Value> values(length + 2);
deba@2312
   236
      
deba@2386
   237
      lpx_get_mat_col(lp, jx, &indices[0], &values[0]);
deba@2312
   238
      
deba@2312
   239
      //The following code does not suppose that the elements of the
deba@2312
   240
      //array indices are sorted
deba@2312
   241
      bool found=false;
deba@2312
   242
      for (int i = 1; i <= length; ++i) {
deba@2386
   243
        if (indices[i]==jx){
deba@2312
   244
          found=true;
deba@2312
   245
          values[i]=value;
deba@2312
   246
          break;
deba@2312
   247
        }
deba@2312
   248
      }
deba@2312
   249
      if (!found){
deba@2312
   250
        ++length;
deba@2386
   251
        indices[length]=ix;
deba@2312
   252
        values[length]=value;
deba@2312
   253
      }
athos@1431
   254
    
deba@2386
   255
      lpx_set_mat_col(lp, jx, length, &indices[0], &values[0]);
athos@1431
   256
    }
athos@1431
   257
  }
athos@1431
   258
deba@2386
   259
  LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
athos@2324
   260
  {
athos@2328
   261
deba@2386
   262
    int length=lpx_get_mat_row(lp, ix, 0, 0);
athos@2328
   263
    
deba@2364
   264
    std::vector<int> indices(length + 1);
deba@2364
   265
    std::vector<Value> values(length + 1);
athos@2328
   266
    
deba@2386
   267
    lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
athos@2328
   268
    
athos@2328
   269
    //The following code does not suppose that the elements of the
athos@2328
   270
    //array indices are sorted
athos@2328
   271
    for (int i = 1; i <= length; ++i) {
deba@2386
   272
      if (indices[i]==jx){
athos@2328
   273
	return values[i];
athos@2328
   274
      }
athos@2328
   275
    }
athos@2324
   276
    return 0;
athos@2328
   277
athos@2324
   278
  }
athos@2324
   279
athos@2324
   280
alpar@1321
   281
  void LpGlpk::_setColLowerBound(int i, Value lo)
alpar@1321
   282
  {
alpar@1321
   283
    if (lo==INF) {
alpar@1321
   284
      //FIXME error
alpar@1321
   285
    }
alpar@1321
   286
    int b=lpx_get_col_type(lp, i);
alpar@1321
   287
    double up=lpx_get_col_ub(lp, i);	
alpar@1321
   288
    if (lo==-INF) {
alpar@1321
   289
      switch (b) {
alpar@1321
   290
      case LPX_FR:
alpar@1321
   291
      case LPX_LO:
alpar@1321
   292
	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
alpar@1321
   293
	break;
alpar@1321
   294
      case LPX_UP:
alpar@1321
   295
	break;
alpar@1321
   296
      case LPX_DB:
alpar@1321
   297
      case LPX_FX:
alpar@1321
   298
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   299
	break;
alpar@1321
   300
      default: ;
alpar@1321
   301
	//FIXME error
alpar@1321
   302
      }
alpar@1321
   303
    } else {
alpar@1321
   304
      switch (b) {
alpar@1321
   305
      case LPX_FR:
alpar@1321
   306
      case LPX_LO:
alpar@1321
   307
	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
alpar@1321
   308
	break;
alpar@1321
   309
      case LPX_UP:	  
alpar@1321
   310
      case LPX_DB:
alpar@1321
   311
      case LPX_FX:
alpar@1321
   312
	if (lo==up) 
alpar@1321
   313
	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
alpar@1321
   314
	else 
alpar@1321
   315
	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
alpar@1321
   316
	break;
alpar@1321
   317
      default: ;
alpar@1321
   318
	//FIXME error
alpar@1321
   319
      }
athos@1261
   320
    }
athos@1261
   321
alpar@1321
   322
  }
athos@2328
   323
deba@2366
   324
  LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
athos@2328
   325
  {
athos@2328
   326
    int b=lpx_get_col_type(lp, i);
athos@2328
   327
      switch (b) {
athos@2328
   328
      case LPX_LO:
athos@2328
   329
      case LPX_DB:
athos@2328
   330
      case LPX_FX:
athos@2328
   331
	return lpx_get_col_lb(lp, i);	
athos@2328
   332
      default: ;
athos@2328
   333
	return -INF;
athos@2328
   334
      }
athos@2328
   335
  }
alpar@1321
   336
  
alpar@1321
   337
  void LpGlpk::_setColUpperBound(int i, Value up)
alpar@1321
   338
  {
alpar@1321
   339
    if (up==-INF) {
alpar@1321
   340
      //FIXME error
athos@1261
   341
    }
alpar@1321
   342
    int b=lpx_get_col_type(lp, i);
alpar@1321
   343
    double lo=lpx_get_col_lb(lp, i);
alpar@1321
   344
    if (up==INF) {
alpar@1321
   345
      switch (b) {
alpar@1321
   346
      case LPX_FR:
alpar@1321
   347
      case LPX_LO:
alpar@1321
   348
	break;
alpar@1321
   349
      case LPX_UP:
alpar@1321
   350
	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
alpar@1321
   351
	break;
alpar@1321
   352
      case LPX_DB:
alpar@1321
   353
      case LPX_FX:
alpar@1321
   354
	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
alpar@1321
   355
	break;
alpar@1321
   356
      default: ;
athos@1261
   357
	//FIXME error
athos@1261
   358
      }
alpar@1321
   359
    } else {
alpar@1321
   360
      switch (b) {
alpar@1321
   361
      case LPX_FR:
alpar@1321
   362
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   363
	break;
alpar@1321
   364
      case LPX_UP:
alpar@1321
   365
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   366
	break;
alpar@1321
   367
      case LPX_LO:
alpar@1321
   368
      case LPX_DB:
alpar@1321
   369
      case LPX_FX:
alpar@1321
   370
	if (lo==up) 
alpar@1321
   371
	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
alpar@1321
   372
	else 
alpar@1321
   373
	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
alpar@1321
   374
	break;
alpar@1321
   375
      default: ;
athos@1261
   376
	//FIXME error
athos@1261
   377
      }
alpar@1321
   378
    }
alpar@1321
   379
  }
athos@2328
   380
deba@2366
   381
  LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
athos@2328
   382
  {
athos@2328
   383
    int b=lpx_get_col_type(lp, i);
athos@2328
   384
      switch (b) {
athos@2328
   385
      case LPX_UP:
athos@2328
   386
      case LPX_DB:
athos@2328
   387
      case LPX_FX:
athos@2328
   388
	return lpx_get_col_ub(lp, i);	
athos@2328
   389
      default: ;
athos@2328
   390
	return INF;
athos@2328
   391
      }
athos@2328
   392
  }
alpar@1321
   393
  
athos@1379
   394
  void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
athos@1379
   395
  {
athos@1379
   396
    //Bad parameter
athos@1379
   397
    if (lb==INF || ub==-INF) {
athos@1379
   398
      //FIXME error
athos@1379
   399
    }
athos@1379
   400
athos@1379
   401
    if (lb == -INF){
athos@1379
   402
      if (ub == INF){
athos@1379
   403
	lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
athos@1379
   404
      }
athos@1379
   405
      else{
athos@1379
   406
	lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
athos@1379
   407
      }
athos@1379
   408
    }
athos@1379
   409
    else{
athos@1379
   410
      if (ub==INF){
athos@1379
   411
	lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
athos@1379
   412
athos@1379
   413
      }
athos@1379
   414
      else{
athos@1379
   415
	if (lb == ub){
athos@1379
   416
	  lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
athos@1379
   417
	}
athos@1379
   418
	else{
athos@1379
   419
	  lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
athos@1379
   420
	}
athos@1379
   421
      }
athos@1379
   422
    }
athos@1379
   423
athos@1379
   424
  }
athos@2328
   425
deba@2366
   426
  void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
athos@2328
   427
  {
athos@2328
   428
athos@2328
   429
    int b=lpx_get_row_type(lp, i);
athos@2328
   430
    switch (b) {
athos@2328
   431
    case LPX_FR:
athos@2328
   432
    case LPX_UP:
athos@2328
   433
      lb = -INF;
athos@2328
   434
	break;
athos@2328
   435
    default: 
athos@2328
   436
      lb=lpx_get_row_lb(lp, i);
athos@2328
   437
    }
athos@2328
   438
athos@2328
   439
    switch (b) {
athos@2328
   440
    case LPX_FR:
athos@2328
   441
    case LPX_LO:
athos@2328
   442
      ub = INF;
athos@2328
   443
	break;
athos@2328
   444
    default: 
athos@2328
   445
      ub=lpx_get_row_ub(lp, i);
athos@2328
   446
    }
athos@2328
   447
    
athos@2328
   448
  }
athos@1261
   449
  
athos@1298
   450
  void LpGlpk::_setObjCoeff(int i, Value obj_coef)
athos@1298
   451
  {
athos@1376
   452
    //i=0 means the constant term (shift)
athos@1298
   453
    lpx_set_obj_coef(lp, i, obj_coef);
athos@1298
   454
  }
athos@1261
   455
deba@2366
   456
  LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
athos@2324
   457
    //i=0 means the constant term (shift)
athos@2324
   458
    return lpx_get_obj_coef(lp, i);
athos@2324
   459
  }
athos@2324
   460
athos@1377
   461
  void LpGlpk::_clearObj()
athos@1376
   462
  {
athos@1377
   463
    for (int i=0;i<=lpx_get_num_cols(lp);++i){
athos@1377
   464
      lpx_set_obj_coef(lp, i, 0);
athos@1376
   465
    }
athos@1376
   466
  }
alpar@1263
   467
alpar@1303
   468
  LpGlpk::SolveExitStatus LpGlpk::_solve()
alpar@1263
   469
  {
athos@2345
   470
    // A way to check the problem to be solved
athos@2345
   471
    //lpx_write_cpxlp(lp,"naittvan.cpx");    
athos@2345
   472
deba@2363
   473
    lpx_std_basis(lp);
athos@1458
   474
    int i =  lpx_simplex(lp);
deba@2363
   475
    
athos@1298
   476
    switch (i) {
athos@1298
   477
    case LPX_E_OK: 
athos@1298
   478
      return SOLVED;
athos@1298
   479
    default:
athos@1298
   480
      return UNSOLVED;
athos@1298
   481
    }
alpar@1263
   482
  }
alpar@1263
   483
deba@2366
   484
  LpGlpk::Value LpGlpk::_getPrimal(int i) const
alpar@1263
   485
  {
athos@1298
   486
    return lpx_get_col_prim(lp,i);
alpar@1263
   487
  }
marci@1787
   488
deba@2366
   489
  LpGlpk::Value LpGlpk::_getDual(int i) const
marci@1787
   490
  {
marci@1787
   491
    return lpx_get_row_dual(lp,i);
marci@1787
   492
  }
alpar@1263
   493
  
deba@2366
   494
  LpGlpk::Value LpGlpk::_getPrimalValue() const
alpar@1312
   495
  {
athos@1314
   496
    return lpx_get_obj_val(lp);
alpar@1312
   497
  }
deba@2366
   498
  bool LpGlpk::_isBasicCol(int i) const
deba@2366
   499
  {
marci@1840
   500
    return (lpx_get_col_stat(lp, i)==LPX_BS);
marci@1840
   501
  }
alpar@1312
   502
  
athos@1298
   503
 
deba@2366
   504
  LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
alpar@1294
   505
  {
athos@1298
   506
    int stat=  lpx_get_status(lp);
athos@1298
   507
    switch (stat) {
athos@1298
   508
    case LPX_UNDEF://Undefined (no solve has been run yet)
athos@1298
   509
      return UNDEFINED;
athos@1458
   510
    case LPX_NOFEAS://There is no feasible solution (primal, I guess)
athos@1458
   511
    case LPX_INFEAS://Infeasible 
athos@1458
   512
      return INFEASIBLE;
athos@1458
   513
    case LPX_UNBND://Unbounded
athos@1458
   514
      return INFINITE;
athos@1458
   515
    case LPX_FEAS://Feasible
athos@1458
   516
      return FEASIBLE;
athos@1458
   517
    case LPX_OPT://Feasible
athos@1458
   518
      return OPTIMAL;
athos@1458
   519
    default:
athos@1458
   520
      return UNDEFINED; //to avoid gcc warning
athos@1458
   521
      //FIXME error
athos@1458
   522
    }
athos@1458
   523
  }
athos@1458
   524
deba@2366
   525
  LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
athos@1458
   526
  {
alpar@1466
   527
    switch (lpx_get_dual_stat(lp)) {
athos@1458
   528
    case LPX_D_UNDEF://Undefined (no solve has been run yet)
athos@1458
   529
      return UNDEFINED;
athos@1540
   530
    case LPX_D_NOFEAS://There is no dual feasible solution 
athos@1460
   531
//    case LPX_D_INFEAS://Infeasible 
athos@1458
   532
      return INFEASIBLE;
athos@1473
   533
    case LPX_D_FEAS://Feasible    
athos@1473
   534
      switch (lpx_get_status(lp)) {
athos@1473
   535
      case LPX_NOFEAS:
athos@1458
   536
	return INFINITE;
athos@1458
   537
      case LPX_OPT:
athos@1458
   538
	return OPTIMAL;
athos@1458
   539
      default:
athos@1458
   540
	return FEASIBLE;
athos@1458
   541
      }
athos@1458
   542
    default:
athos@1458
   543
      return UNDEFINED; //to avoid gcc warning
athos@1458
   544
      //FIXME error
athos@1458
   545
    }
athos@1458
   546
  }
athos@1458
   547
deba@2366
   548
  LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
athos@1458
   549
  {
athos@1460
   550
      //int stat=  lpx_get_status(lp);
athos@1458
   551
    int statp=  lpx_get_prim_stat(lp);
athos@1458
   552
    int statd=  lpx_get_dual_stat(lp);
athos@1464
   553
    if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
athos@1460
   554
	return PRIMAL_DUAL_FEASIBLE;
athos@1464
   555
    if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
athos@1460
   556
	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
athos@1464
   557
    if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
athos@1460
   558
	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
athos@1464
   559
    if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
athos@1460
   560
	return PRIMAL_DUAL_INFEASIBLE;
athos@1460
   561
    //In all other cases
athos@1460
   562
    return UNKNOWN;
alpar@1294
   563
  }
alpar@1263
   564
alpar@1312
   565
  void LpGlpk::_setMax()
alpar@1312
   566
  {
alpar@1321
   567
    lpx_set_obj_dir(lp, LPX_MAX);
alpar@1321
   568
  }
alpar@1321
   569
alpar@1312
   570
  void LpGlpk::_setMin()
alpar@1312
   571
  {
alpar@1321
   572
    lpx_set_obj_dir(lp, LPX_MIN);
alpar@1321
   573
  }
alpar@1321
   574
deba@2366
   575
  bool LpGlpk::_isMax() const
athos@2324
   576
  {
athos@2324
   577
    return (lpx_get_obj_dir(lp)==LPX_MAX);
athos@2324
   578
  }
athos@2324
   579
alpar@1321
   580
 
athos@2324
   581
alpar@1321
   582
  void LpGlpk::messageLevel(int m)
alpar@1321
   583
  {
alpar@1321
   584
    lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
alpar@1321
   585
  }
alpar@1312
   586
alpar@1326
   587
  void LpGlpk::presolver(bool b)
alpar@1326
   588
  {
alpar@1326
   589
    lpx_set_int_parm(lp, LPX_K_PRESOL, b);
alpar@1326
   590
  }
alpar@1326
   591
alpar@1312
   592
 
athos@1261
   593
} //END OF NAMESPACE LEMON