src/lemon/lp_glpk.cc
author athos
Fri, 20 May 2005 09:43:40 +0000
changeset 1432 46b088b01f88
parent 1431 ad44b1dd8013
permissions -rw-r--r--
Functions _eraseRow(), _eraseCol(). Not yet implemented for cplex.
athos@1261
     1
/* -*- C++ -*-
athos@1261
     2
 * src/lemon/lp_glpk.cc - Part of LEMON, a generic C++ optimization library
athos@1261
     3
 *
athos@1261
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
athos@1261
     6
 *
athos@1261
     7
 * Permission to use, modify and distribute this software is granted
athos@1261
     8
 * provided that this copyright notice appears in all copies. For
athos@1261
     9
 * precise terms see the accompanying LICENSE file.
athos@1261
    10
 *
athos@1261
    11
 * This software is provided "AS IS" with no warranty of any kind,
athos@1261
    12
 * express or implied, and with no claim as to its suitability for any
athos@1261
    13
 * purpose.
athos@1261
    14
 *
athos@1261
    15
 */
athos@1261
    16
athos@1261
    17
#ifndef LEMON_LP_GLPK_CC
athos@1261
    18
#define LEMON_LP_GLPK_CC
athos@1261
    19
athos@1261
    20
///\file
athos@1261
    21
///\brief Implementation of the LEMON-GLPK lp solver interface.
athos@1261
    22
ladanyi@1305
    23
#include <lemon/lp_glpk.h>
athos@1261
    24
athos@1261
    25
namespace lemon {
athos@1261
    26
alpar@1364
    27
  ///\e
alpar@1364
    28
alpar@1364
    29
  ///\bug Unimplemented!
alpar@1364
    30
  ///
alpar@1364
    31
  LpSolverBase &LpGlpk::_newLp()
alpar@1364
    32
  {
alpar@1368
    33
    LpSolverBase *tmp=0;
alpar@1368
    34
    return *tmp;
alpar@1364
    35
  }
alpar@1364
    36
  
alpar@1364
    37
  ///\e
alpar@1364
    38
alpar@1364
    39
  ///\bug Unimplemented!
alpar@1364
    40
  ///
alpar@1364
    41
  LpSolverBase &LpGlpk::_copyLp()
alpar@1364
    42
  {
alpar@1368
    43
    LpSolverBase *tmp=0;
alpar@1368
    44
    return *tmp;
alpar@1364
    45
  }
alpar@1364
    46
alpar@1321
    47
  LpGlpk::LpGlpk() : Parent(), 
alpar@1321
    48
		     lp(lpx_create_prob()) {
alpar@1321
    49
    ///\todo constrol function for this:
alpar@1321
    50
    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
alpar@1321
    51
    messageLevel(0);
alpar@1321
    52
  }
alpar@1321
    53
  
alpar@1321
    54
  LpGlpk::~LpGlpk() {
alpar@1321
    55
    lpx_delete_prob(lp);
alpar@1321
    56
  }
alpar@1321
    57
  
alpar@1321
    58
  int LpGlpk::_addCol() { 
alpar@1321
    59
    int i=lpx_add_cols(lp, 1);
alpar@1321
    60
    _setColLowerBound(i, -INF);
alpar@1321
    61
    _setColUpperBound(i, INF);
alpar@1321
    62
    return i;
alpar@1321
    63
  }
alpar@1321
    64
alpar@1321
    65
  int LpGlpk::_addRow() { 
alpar@1321
    66
    int i=lpx_add_rows(lp, 1);
alpar@1321
    67
    return i;
alpar@1321
    68
  }
alpar@1321
    69
alpar@1321
    70
  
athos@1432
    71
  void LpGlpk::_eraseCol(int i) {
athos@1432
    72
    int cols[2];
athos@1432
    73
    cols[1]=i;
athos@1432
    74
    lpx_del_cols(lp, 1, cols);
athos@1432
    75
  }
athos@1432
    76
  
athos@1432
    77
  void LpGlpk::_eraseRow(int i) {
athos@1432
    78
    int rows[2];
athos@1432
    79
    rows[1]=i;
athos@1432
    80
    lpx_del_rows(lp, 1, rows);
athos@1432
    81
  }
athos@1432
    82
alpar@1321
    83
  void LpGlpk::_setRowCoeffs(int i, 
alpar@1321
    84
			     int length,
alpar@1321
    85
			     const int   * indices, 
alpar@1321
    86
			     const Value   * values )
alpar@1321
    87
  {
alpar@1321
    88
    lpx_set_mat_row(lp, i, length,
alpar@1321
    89
		    const_cast<int * >(indices) ,
alpar@1321
    90
		    const_cast<Value * >(values));
alpar@1321
    91
  }
alpar@1321
    92
  
alpar@1321
    93
  void LpGlpk::_setColCoeffs(int i, 
alpar@1321
    94
			     int length,
alpar@1321
    95
			     const int   * indices, 
alpar@1321
    96
			     const Value   * values)
alpar@1321
    97
  {
alpar@1321
    98
    lpx_set_mat_col(lp, i, length,
alpar@1321
    99
		    const_cast<int * >(indices),
alpar@1321
   100
		    const_cast<Value * >(values));
alpar@1321
   101
  }
athos@1431
   102
athos@1431
   103
athos@1431
   104
  void LpGlpk::_setCoeff(int row, int col, Value value) 
athos@1431
   105
  {
athos@1431
   106
    ///FIXME Of course this is not efficient at all, but GLPK knows not more.
athos@1431
   107
    // First approach: get one row, apply changes and set it again
athos@1431
   108
    //(one idea to improve this: maybe it is better to do this with 1 coloumn)
athos@1431
   109
    
athos@1431
   110
    int mem_length=2+lpx_get_num_cols(lp);
athos@1431
   111
    int* indices = new int[mem_length];
athos@1431
   112
    Value* values = new Value[mem_length];
athos@1431
   113
    
athos@1431
   114
athos@1431
   115
    int length=lpx_get_mat_row(lp, row, indices, values);
athos@1431
   116
athos@1431
   117
    //The following code does not suppose that the elements of the array indices are sorted
athos@1431
   118
    int i=1;
athos@1431
   119
    bool found=false;
athos@1431
   120
    while (i <= length && !found){
athos@1431
   121
      if (indices[i]==col){
athos@1431
   122
	found = true;
athos@1431
   123
	values[i]=value;
athos@1431
   124
      }
athos@1431
   125
      ++i;
athos@1431
   126
    }
athos@1431
   127
    if (!found){
athos@1431
   128
      ++length;
athos@1431
   129
      indices[length]=col;
athos@1431
   130
      values[length]=value;
athos@1431
   131
    }
athos@1431
   132
    
athos@1431
   133
    lpx_set_mat_row(lp, row, length, indices, values);
athos@1431
   134
    delete [] indices;
athos@1431
   135
    delete [] values;
athos@1431
   136
    
athos@1431
   137
  }
athos@1431
   138
alpar@1321
   139
  void LpGlpk::_setColLowerBound(int i, Value lo)
alpar@1321
   140
  {
alpar@1321
   141
    if (lo==INF) {
alpar@1321
   142
      //FIXME error
alpar@1321
   143
    }
alpar@1321
   144
    int b=lpx_get_col_type(lp, i);
alpar@1321
   145
    double up=lpx_get_col_ub(lp, i);	
alpar@1321
   146
    if (lo==-INF) {
alpar@1321
   147
      switch (b) {
alpar@1321
   148
      case LPX_FR:
alpar@1321
   149
      case LPX_LO:
alpar@1321
   150
	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
alpar@1321
   151
	break;
alpar@1321
   152
      case LPX_UP:
alpar@1321
   153
	break;
alpar@1321
   154
      case LPX_DB:
alpar@1321
   155
      case LPX_FX:
alpar@1321
   156
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   157
	break;
alpar@1321
   158
      default: ;
alpar@1321
   159
	//FIXME error
alpar@1321
   160
      }
alpar@1321
   161
    } else {
alpar@1321
   162
      switch (b) {
alpar@1321
   163
      case LPX_FR:
alpar@1321
   164
      case LPX_LO:
alpar@1321
   165
	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
alpar@1321
   166
	break;
alpar@1321
   167
      case LPX_UP:	  
alpar@1321
   168
      case LPX_DB:
alpar@1321
   169
      case LPX_FX:
alpar@1321
   170
	if (lo==up) 
alpar@1321
   171
	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
alpar@1321
   172
	else 
alpar@1321
   173
	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
alpar@1321
   174
	break;
alpar@1321
   175
      default: ;
alpar@1321
   176
	//FIXME error
alpar@1321
   177
      }
athos@1261
   178
    }
athos@1261
   179
alpar@1321
   180
  }
alpar@1321
   181
  
alpar@1321
   182
  void LpGlpk::_setColUpperBound(int i, Value up)
alpar@1321
   183
  {
alpar@1321
   184
    if (up==-INF) {
alpar@1321
   185
      //FIXME error
athos@1261
   186
    }
alpar@1321
   187
    int b=lpx_get_col_type(lp, i);
alpar@1321
   188
    double lo=lpx_get_col_lb(lp, i);
alpar@1321
   189
    if (up==INF) {
alpar@1321
   190
      switch (b) {
alpar@1321
   191
      case LPX_FR:
alpar@1321
   192
      case LPX_LO:
alpar@1321
   193
	break;
alpar@1321
   194
      case LPX_UP:
alpar@1321
   195
	lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
alpar@1321
   196
	break;
alpar@1321
   197
      case LPX_DB:
alpar@1321
   198
      case LPX_FX:
alpar@1321
   199
	lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
alpar@1321
   200
	break;
alpar@1321
   201
      default: ;
athos@1261
   202
	//FIXME error
athos@1261
   203
      }
alpar@1321
   204
    } else {
alpar@1321
   205
      switch (b) {
alpar@1321
   206
      case LPX_FR:
alpar@1321
   207
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   208
	break;
alpar@1321
   209
      case LPX_UP:
alpar@1321
   210
	lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
alpar@1321
   211
	break;
alpar@1321
   212
      case LPX_LO:
alpar@1321
   213
      case LPX_DB:
alpar@1321
   214
      case LPX_FX:
alpar@1321
   215
	if (lo==up) 
alpar@1321
   216
	  lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
alpar@1321
   217
	else 
alpar@1321
   218
	  lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
alpar@1321
   219
	break;
alpar@1321
   220
      default: ;
athos@1261
   221
	//FIXME error
athos@1261
   222
      }
alpar@1321
   223
    }
alpar@1321
   224
  }
alpar@1321
   225
  
athos@1405
   226
//   void LpGlpk::_setRowLowerBound(int i, Value lo)
athos@1405
   227
//   {
athos@1405
   228
//     if (lo==INF) {
athos@1405
   229
//       //FIXME error
athos@1405
   230
//     }
athos@1405
   231
//     int b=lpx_get_row_type(lp, i);
athos@1405
   232
//     double up=lpx_get_row_ub(lp, i);	
athos@1405
   233
//     if (lo==-INF) {
athos@1405
   234
//       switch (b) {
athos@1405
   235
//       case LPX_FR:
athos@1405
   236
//       case LPX_LO:
athos@1405
   237
// 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
athos@1405
   238
// 	break;
athos@1405
   239
//       case LPX_UP:
athos@1405
   240
// 	break;
athos@1405
   241
//       case LPX_DB:
athos@1405
   242
//       case LPX_FX:
athos@1405
   243
// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
athos@1405
   244
// 	break;
athos@1405
   245
//       default: ;
athos@1405
   246
// 	//FIXME error
athos@1405
   247
//       }
athos@1405
   248
//     } else {
athos@1405
   249
//       switch (b) {
athos@1405
   250
//       case LPX_FR:
athos@1405
   251
//       case LPX_LO:
athos@1405
   252
// 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
athos@1405
   253
// 	break;
athos@1405
   254
//       case LPX_UP:	  
athos@1405
   255
//       case LPX_DB:
athos@1405
   256
//       case LPX_FX:
athos@1405
   257
// 	if (lo==up) 
athos@1405
   258
// 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
athos@1405
   259
// 	else 
athos@1405
   260
// 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
athos@1405
   261
// 	break;
athos@1405
   262
//       default: ;
athos@1405
   263
// 	//FIXME error
athos@1405
   264
//       }
athos@1405
   265
//     }
athos@1405
   266
//   }
athos@1261
   267
  
athos@1405
   268
//   void LpGlpk::_setRowUpperBound(int i, Value up)
athos@1405
   269
//   {
athos@1405
   270
//     if (up==-INF) {
athos@1405
   271
//       //FIXME error
athos@1405
   272
//     }
athos@1405
   273
//     int b=lpx_get_row_type(lp, i);
athos@1405
   274
//     double lo=lpx_get_row_lb(lp, i);
athos@1405
   275
//     if (up==INF) {
athos@1405
   276
//       switch (b) {
athos@1405
   277
//       case LPX_FR:
athos@1405
   278
//       case LPX_LO:
athos@1405
   279
// 	break;
athos@1405
   280
//       case LPX_UP:
athos@1405
   281
// 	lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
athos@1405
   282
// 	break;
athos@1405
   283
//       case LPX_DB:
athos@1405
   284
//       case LPX_FX:
athos@1405
   285
// 	lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
athos@1405
   286
// 	break;
athos@1405
   287
//       default: ;
athos@1405
   288
// 	//FIXME error
athos@1405
   289
//       }
athos@1405
   290
//     } else {
athos@1405
   291
//       switch (b) {
athos@1405
   292
//       case LPX_FR:
athos@1405
   293
// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
athos@1405
   294
// 	break;
athos@1405
   295
//       case LPX_UP:
athos@1405
   296
// 	lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
athos@1405
   297
// 	break;
athos@1405
   298
//       case LPX_LO:
athos@1405
   299
//       case LPX_DB:
athos@1405
   300
//       case LPX_FX:
athos@1405
   301
// 	if (lo==up) 
athos@1405
   302
// 	  lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
athos@1405
   303
// 	else 
athos@1405
   304
// 	  lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
athos@1405
   305
// 	break;
athos@1405
   306
//       default: ;
athos@1405
   307
// 	//FIXME error
athos@1405
   308
//       }
athos@1405
   309
//     }
athos@1405
   310
//   }
athos@1379
   311
athos@1379
   312
  void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
athos@1379
   313
  {
athos@1379
   314
    //Bad parameter
athos@1379
   315
    if (lb==INF || ub==-INF) {
athos@1379
   316
      //FIXME error
athos@1379
   317
    }
athos@1379
   318
athos@1379
   319
    if (lb == -INF){
athos@1379
   320
      if (ub == INF){
athos@1379
   321
	lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
athos@1379
   322
      }
athos@1379
   323
      else{
athos@1379
   324
	lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
athos@1379
   325
      }
athos@1379
   326
    }
athos@1379
   327
    else{
athos@1379
   328
      if (ub==INF){
athos@1379
   329
	lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
athos@1379
   330
athos@1379
   331
      }
athos@1379
   332
      else{
athos@1379
   333
	if (lb == ub){
athos@1379
   334
	  lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
athos@1379
   335
	}
athos@1379
   336
	else{
athos@1379
   337
	  lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
athos@1379
   338
	}
athos@1379
   339
      }
athos@1379
   340
    }
athos@1379
   341
athos@1379
   342
  }
athos@1261
   343
  
athos@1298
   344
  void LpGlpk::_setObjCoeff(int i, Value obj_coef)
athos@1298
   345
  {
athos@1376
   346
    //i=0 means the constant term (shift)
athos@1298
   347
    lpx_set_obj_coef(lp, i, obj_coef);
athos@1298
   348
  }
athos@1261
   349
athos@1377
   350
  void LpGlpk::_clearObj()
athos@1376
   351
  {
athos@1377
   352
    for (int i=0;i<=lpx_get_num_cols(lp);++i){
athos@1377
   353
      lpx_set_obj_coef(lp, i, 0);
athos@1376
   354
    }
athos@1376
   355
  }
athos@1377
   356
//   void LpGlpk::_setObj(int length,
athos@1377
   357
// 		       int  const * indices, 
athos@1377
   358
// 		       Value  const * values )
athos@1377
   359
//   {
athos@1377
   360
//     Value new_values[1+lpx_num_cols()];
athos@1377
   361
//     for (i=0;i<=lpx_num_cols();++i){
athos@1377
   362
//       new_values[i]=0;
athos@1377
   363
//     }
athos@1377
   364
//     for (i=1;i<=length;++i){
athos@1377
   365
//       new_values[indices[i]]=values[i];
athos@1377
   366
//     }
athos@1377
   367
    
athos@1377
   368
//     for (i=0;i<=lpx_num_cols();++i){
athos@1377
   369
//       lpx_set_obj_coef(lp, i, new_values[i]);
athos@1377
   370
//     }
athos@1377
   371
//   }
alpar@1263
   372
alpar@1303
   373
  LpGlpk::SolveExitStatus LpGlpk::_solve()
alpar@1263
   374
  {
athos@1298
   375
    int i=  lpx_simplex(lp);
athos@1298
   376
    switch (i) {
athos@1298
   377
    case LPX_E_OK: 
athos@1298
   378
      return SOLVED;
athos@1298
   379
      break;
athos@1298
   380
    default:
athos@1298
   381
      return UNSOLVED;
athos@1298
   382
    }
alpar@1263
   383
  }
alpar@1263
   384
alpar@1293
   385
  LpGlpk::Value LpGlpk::_getPrimal(int i)
alpar@1263
   386
  {
athos@1298
   387
    return lpx_get_col_prim(lp,i);
alpar@1263
   388
  }
alpar@1263
   389
  
alpar@1312
   390
  LpGlpk::Value LpGlpk::_getPrimalValue()
alpar@1312
   391
  {
athos@1314
   392
    return lpx_get_obj_val(lp);
alpar@1312
   393
  }
alpar@1312
   394
  
athos@1298
   395
 
alpar@1312
   396
  LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
alpar@1294
   397
  {
athos@1298
   398
    int stat=  lpx_get_status(lp);
athos@1298
   399
    switch (stat) {
athos@1298
   400
    case LPX_UNDEF://Undefined (no solve has been run yet)
athos@1298
   401
      return UNDEFINED;
athos@1298
   402
      break;
athos@1298
   403
    case LPX_NOFEAS://There is no feasible solution (primal, I guess)
athos@1298
   404
    case LPX_INFEAS://Infeasible 
athos@1298
   405
      return INFEASIBLE;
athos@1298
   406
      break;
athos@1298
   407
    case LPX_UNBND://Unbounded
athos@1298
   408
      return INFINITE;
athos@1298
   409
      break;
athos@1298
   410
    case LPX_FEAS://Feasible
alpar@1300
   411
      return FEASIBLE;
athos@1298
   412
      break;
athos@1298
   413
    case LPX_OPT://Feasible
athos@1298
   414
      return OPTIMAL;
athos@1298
   415
      break;
alpar@1300
   416
    default:
alpar@1300
   417
      return UNDEFINED; //to avoid gcc warning
athos@1298
   418
      //FIXME error
athos@1298
   419
    }
alpar@1294
   420
  }
alpar@1263
   421
alpar@1263
   422
alpar@1312
   423
  void LpGlpk::_setMax()
alpar@1312
   424
  {
alpar@1321
   425
    lpx_set_obj_dir(lp, LPX_MAX);
alpar@1321
   426
  }
alpar@1321
   427
alpar@1312
   428
  void LpGlpk::_setMin()
alpar@1312
   429
  {
alpar@1321
   430
    lpx_set_obj_dir(lp, LPX_MIN);
alpar@1321
   431
  }
alpar@1321
   432
alpar@1321
   433
 
alpar@1321
   434
  void LpGlpk::messageLevel(int m)
alpar@1321
   435
  {
alpar@1321
   436
    lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
alpar@1321
   437
  }
alpar@1312
   438
alpar@1326
   439
  void LpGlpk::presolver(bool b)
alpar@1326
   440
  {
alpar@1326
   441
    lpx_set_int_parm(lp, LPX_K_PRESOL, b);
alpar@1326
   442
  }
alpar@1326
   443
alpar@1312
   444
 
athos@1261
   445
} //END OF NAMESPACE LEMON
athos@1261
   446
athos@1261
   447
#endif //LEMON_LP_GLPK_CC