↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -10,102 +10,105 @@
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\file
20 20
///\brief Implementation of the CBC MIP solver interface.
21 21

	
22 22
#include "cbc.h"
23 23

	
24 24
#include <coin/CoinModel.hpp>
25 25
#include <coin/CbcModel.hpp>
26 26
#include <coin/OsiSolverInterface.hpp>
27 27

	
28 28
#ifdef COIN_HAS_CLP
29 29
#include "coin/OsiClpSolverInterface.hpp"
30 30
#endif
31 31
#ifdef COIN_HAS_OSL
32 32
#include "coin/OsiOslSolverInterface.hpp"
33 33
#endif
34 34

	
35 35
#include "coin/CbcCutGenerator.hpp"
36 36
#include "coin/CbcHeuristicLocal.hpp"
37 37
#include "coin/CbcHeuristicGreedy.hpp"
38 38
#include "coin/CbcHeuristicFPump.hpp"
39 39
#include "coin/CbcHeuristicRINS.hpp"
40 40

	
41 41
#include "coin/CglGomory.hpp"
42 42
#include "coin/CglProbing.hpp"
43 43
#include "coin/CglKnapsackCover.hpp"
44 44
#include "coin/CglOddHole.hpp"
45 45
#include "coin/CglClique.hpp"
46 46
#include "coin/CglFlowCover.hpp"
47 47
#include "coin/CglMixedIntegerRounding.hpp"
48 48

	
49 49
#include "coin/CbcHeuristic.hpp"
50 50

	
51 51
namespace lemon {
52 52

	
53 53
  CbcMip::CbcMip() {
54 54
    _prob = new CoinModel();
55 55
    _prob->setProblemName("LEMON");
56 56
    _osi_solver = 0;
57 57
    _cbc_model = 0;
58
    messageLevel(MESSAGE_NOTHING);
58 59
  }
59 60

	
60 61
  CbcMip::CbcMip(const CbcMip& other) {
61 62
    _prob = new CoinModel(*other._prob);
63
    _prob->setProblemName("LEMON");
62 64
    _osi_solver = 0;
63 65
    _cbc_model = 0;
66
    messageLevel(MESSAGE_NOTHING);
64 67
  }
65 68

	
66 69
  CbcMip::~CbcMip() {
67 70
    delete _prob;
68 71
    if (_osi_solver) delete _osi_solver;
69 72
    if (_cbc_model) delete _cbc_model;
70 73
  }
71 74

	
72 75
  const char* CbcMip::_solverName() const { return "CbcMip"; }
73 76

	
74 77
  int CbcMip::_addCol() {
75 78
    _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0, 0, false);
76 79
    return _prob->numberColumns() - 1;
77 80
  }
78 81

	
79 82
  CbcMip* CbcMip::newSolver() const {
80 83
    CbcMip* newlp = new CbcMip;
81 84
    return newlp;
82 85
  }
83 86

	
84 87
  CbcMip* CbcMip::cloneSolver() const {
85 88
    CbcMip* copylp = new CbcMip(*this);
86 89
    return copylp;
87 90
  }
88 91

	
89 92
  int CbcMip::_addRow() {
90 93
    _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
91 94
    return _prob->numberRows() - 1;
92 95
  }
93 96

	
94 97

	
95 98
  void CbcMip::_eraseCol(int i) {
96 99
    _prob->deleteColumn(i);
97 100
  }
98 101

	
99 102
  void CbcMip::_eraseRow(int i) {
100 103
    _prob->deleteRow(i);
101 104
  }
102 105

	
103 106
  void CbcMip::_eraseColId(int i) {
104 107
    cols.eraseIndex(i);
105 108
  }
106 109

	
107 110
  void CbcMip::_eraseRowId(int i) {
108 111
    rows.eraseIndex(i);
109 112
  }
110 113

	
111 114
  void CbcMip::_getColName(int c, std::string& name) const {
... ...
@@ -225,114 +228,98 @@
225 228
    int num = _prob->numberColumns();
226 229
    for (int i = 0; i < num; ++i) {
227 230
      _prob->setColumnObjective(i, 0.0);
228 231
    }
229 232
    for (ExprIterator it = b; it != e; ++it) {
230 233
      _prob->setColumnObjective(it->first, it->second);
231 234
    }
232 235
  }
233 236

	
234 237
  void CbcMip::_getObjCoeffs(InsertIterator b) const {
235 238
    int num = _prob->numberColumns();
236 239
    for (int i = 0; i < num; ++i) {
237 240
      Value coef = _prob->getColumnObjective(i);
238 241
      if (coef != 0.0) {
239 242
        *b = std::make_pair(i, coef);
240 243
        ++b;
241 244
      }
242 245
    }
243 246
  }
244 247

	
245 248
  void CbcMip::_setObjCoeff(int i, Value obj_coef) {
246 249
    _prob->setColumnObjective(i, obj_coef);
247 250
  }
248 251

	
249 252
  CbcMip::Value CbcMip::_getObjCoeff(int i) const {
250 253
    return _prob->getColumnObjective(i);
251 254
  }
252 255

	
253 256
  CbcMip::SolveExitStatus CbcMip::_solve() {
254 257

	
255 258
    if (_osi_solver) {
256 259
      delete _osi_solver;
257 260
    }
258 261
#ifdef COIN_HAS_CLP
259 262
    _osi_solver = new OsiClpSolverInterface();
260 263
#elif COIN_HAS_OSL
261 264
    _osi_solver = new OsiOslSolverInterface();
262 265
#else
263 266
#error Cannot instantiate Osi solver
264 267
#endif
265 268

	
266 269
    _osi_solver->loadFromCoinModel(*_prob);
267 270

	
268 271
    if (_cbc_model) {
269 272
      delete _cbc_model;
270 273
    }
271 274
    _cbc_model= new CbcModel(*_osi_solver);
272 275

	
273
    switch (_message_level) {
274
    case MESSAGE_NO_OUTPUT:
275
      _osi_solver->messageHandler()->setLogLevel(0);
276
      _cbc_model->setLogLevel(0);
277
      break;
278
    case MESSAGE_ERROR_MESSAGE:
279
      _osi_solver->messageHandler()->setLogLevel(1);
280
      _cbc_model->setLogLevel(1);
281
      break;
282
    case MESSAGE_NORMAL_OUTPUT:
283
      _osi_solver->messageHandler()->setLogLevel(2);
284
      _cbc_model->setLogLevel(2);
285
      break;
286
    case MESSAGE_FULL_OUTPUT:
287
      _osi_solver->messageHandler()->setLogLevel(3);
288
      _cbc_model->setLogLevel(3);
289
      break;
290
    }
276
    _osi_solver->messageHandler()->setLogLevel(_message_level);
277
    _cbc_model->setLogLevel(_message_level);
291 278

	
292 279
    _cbc_model->initialSolve();
293 280
    _cbc_model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
294 281

	
295 282
    if (!_cbc_model->isInitialSolveAbandoned() &&
296 283
        _cbc_model->isInitialSolveProvenOptimal() &&
297 284
        !_cbc_model->isInitialSolveProvenPrimalInfeasible() &&
298 285
        !_cbc_model->isInitialSolveProvenDualInfeasible()) {
299 286

	
300 287
      CglProbing generator1;
301 288
      generator1.setUsingObjective(true);
302 289
      generator1.setMaxPass(3);
303 290
      generator1.setMaxProbe(100);
304 291
      generator1.setMaxLook(50);
305 292
      generator1.setRowCuts(3);
306 293
      _cbc_model->addCutGenerator(&generator1, -1, "Probing");
307 294

	
308 295
      CglGomory generator2;
309 296
      generator2.setLimit(300);
310 297
      _cbc_model->addCutGenerator(&generator2, -1, "Gomory");
311 298

	
312 299
      CglKnapsackCover generator3;
313 300
      _cbc_model->addCutGenerator(&generator3, -1, "Knapsack");
314 301

	
315 302
      CglOddHole generator4;
316 303
      generator4.setMinimumViolation(0.005);
317 304
      generator4.setMinimumViolationPer(0.00002);
318 305
      generator4.setMaximumEntries(200);
319 306
      _cbc_model->addCutGenerator(&generator4, -1, "OddHole");
320 307

	
321 308
      CglClique generator5;
322 309
      generator5.setStarCliqueReport(false);
323 310
      generator5.setRowCliqueReport(false);
324 311
      _cbc_model->addCutGenerator(&generator5, -1, "Clique");
325 312

	
326 313
      CglMixedIntegerRounding mixedGen;
327 314
      _cbc_model->addCutGenerator(&mixedGen, -1, "MixedIntegerRounding");
328 315

	
329 316
      CglFlowCover flowGen;
330 317
      _cbc_model->addCutGenerator(&flowGen, -1, "FlowCover");
331 318

	
332 319
#ifdef COIN_HAS_CLP
333 320
      OsiClpSolverInterface* osiclp =
334 321
        dynamic_cast<OsiClpSolverInterface*>(_cbc_model->solver());
335 322
      if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) {
336 323
        osiclp->setupForRepeatedUse(2, 0);
337 324
      }
338 325
#endif
... ...
@@ -408,53 +395,69 @@
408 395
      break;
409 396
    }
410 397
  }
411 398

	
412 399
  CbcMip::Sense CbcMip::_getSense() const {
413 400
    if (_prob->optimizationDirection() > 0.0) {
414 401
      return MIN;
415 402
    } else if (_prob->optimizationDirection() < 0.0) {
416 403
      return MAX;
417 404
    } else {
418 405
      LEMON_ASSERT(false, "Wrong sense");
419 406
      return CbcMip::Sense();
420 407
    }
421 408
  }
422 409

	
423 410
  void CbcMip::_setColType(int i, CbcMip::ColTypes col_type) {
424 411
    switch (col_type){
425 412
    case INTEGER:
426 413
      _prob->setInteger(i);
427 414
      break;
428 415
    case REAL:
429 416
      _prob->setContinuous(i);
430 417
      break;
431 418
    default:;
432 419
      LEMON_ASSERT(false, "Wrong sense");
433 420
    }
434 421
  }
435 422

	
436 423
  CbcMip::ColTypes CbcMip::_getColType(int i) const {
437 424
    return _prob->getColumnIsInteger(i) ? INTEGER : REAL;
438 425
  }
439 426

	
440 427
  void CbcMip::_clear() {
441 428
    delete _prob;
442 429
    if (_osi_solver) {
443 430
      delete _osi_solver;
444 431
      _osi_solver = 0;
445 432
    }
446 433
    if (_cbc_model) {
447 434
      delete _cbc_model;
448 435
      _cbc_model = 0;
449 436
    }
450 437

	
451 438
    _prob = new CoinModel();
452 439
    rows.clear();
453 440
    cols.clear();
454 441
  }
455 442

	
456
  void CbcMip::messageLevel(MessageLevel m) {
457
    _message_level = m;
443
  void CbcMip::_messageLevel(MessageLevel level) {
444
    switch (level) {
445
    case MESSAGE_NOTHING:
446
      _message_level = 0;
447
      break;
448
    case MESSAGE_ERROR:
449
      _message_level = 1;
450
      break;
451
    case MESSAGE_WARNING:
452
      _message_level = 1;
453
      break;
454
    case MESSAGE_NORMAL:
455
      _message_level = 2;
456
      break;
457
    case MESSAGE_VERBOSE:
458
      _message_level = 3;
459
      break;
460
    }
458 461
  }
459 462

	
460 463
} //END OF NAMESPACE LEMON
Ignore white space 6 line context
... ...
@@ -70,81 +70,60 @@
70 70
    virtual void _eraseRowId(int i);
71 71

	
72 72
    virtual void _getColName(int col, std::string& name) const;
73 73
    virtual void _setColName(int col, const std::string& name);
74 74
    virtual int _colByName(const std::string& name) const;
75 75

	
76 76
    virtual void _getRowName(int row, std::string& name) const;
77 77
    virtual void _setRowName(int row, const std::string& name);
78 78
    virtual int _rowByName(const std::string& name) const;
79 79

	
80 80
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
81 81
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
82 82

	
83 83
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
84 84
    virtual void _getColCoeffs(int i, InsertIterator b) const;
85 85

	
86 86
    virtual void _setCoeff(int row, int col, Value value);
87 87
    virtual Value _getCoeff(int row, int col) const;
88 88

	
89 89
    virtual void _setColLowerBound(int i, Value value);
90 90
    virtual Value _getColLowerBound(int i) const;
91 91
    virtual void _setColUpperBound(int i, Value value);
92 92
    virtual Value _getColUpperBound(int i) const;
93 93

	
94 94
    virtual void _setRowLowerBound(int i, Value value);
95 95
    virtual Value _getRowLowerBound(int i) const;
96 96
    virtual void _setRowUpperBound(int i, Value value);
97 97
    virtual Value _getRowUpperBound(int i) const;
98 98

	
99 99
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
100 100
    virtual void _getObjCoeffs(InsertIterator b) const;
101 101

	
102 102
    virtual void _setObjCoeff(int i, Value obj_coef);
103 103
    virtual Value _getObjCoeff(int i) const;
104 104

	
105 105
    virtual void _setSense(Sense sense);
106 106
    virtual Sense _getSense() const;
107 107

	
108 108
    virtual ColTypes _getColType(int col) const;
109 109
    virtual void _setColType(int col, ColTypes col_type);
110 110

	
111 111
    virtual SolveExitStatus _solve();
112 112
    virtual ProblemType _getType() const;
113 113
    virtual Value _getSol(int i) const;
114 114
    virtual Value _getSolValue() const;
115 115

	
116 116
    virtual void _clear();
117 117

	
118
  public:
118
    virtual void _messageLevel(MessageLevel level);
119
    void _applyMessageLevel();
119 120

	
120
    ///Enum for \c messageLevel() parameter
121
    enum MessageLevel {
122
      /// no output (default value)
123
      MESSAGE_NO_OUTPUT = 0,
124
      /// error messages only
125
      MESSAGE_ERROR_MESSAGE = 1,
126
      /// normal output
127
      MESSAGE_NORMAL_OUTPUT = 2,
128
      /// full output (includes informational messages)
129
      MESSAGE_FULL_OUTPUT = 3
130
    };
121
    int _message_level;
131 122

	
132
  private:
133

	
134
    MessageLevel _message_level;
135

	
136
  public:
137

	
138
    ///Set the verbosity of the messages
139

	
140
    ///Set the verbosity of the messages
141
    ///
142
    ///\param m is the level of the messages output by the solver routines.
143
    void messageLevel(MessageLevel m);
144

	
123
    
145 124

	
146 125
  };
147 126

	
148 127
}
149 128

	
150 129
#endif
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <lemon/clp.h>
20 20
#include <coin/ClpSimplex.hpp>
21 21

	
22 22
namespace lemon {
23 23

	
24 24
  ClpLp::ClpLp() {
25 25
    _prob = new ClpSimplex();
26 26
    _init_temporals();
27
    messageLevel(MESSAGE_NO_OUTPUT);
27
    messageLevel(MESSAGE_NOTHING);
28 28
  }
29 29

	
30 30
  ClpLp::ClpLp(const ClpLp& other) {
31 31
    _prob = new ClpSimplex(*other._prob);
32 32
    rows = other.rows;
33 33
    cols = other.cols;
34 34
    _init_temporals();
35
    messageLevel(MESSAGE_NO_OUTPUT);
35
    messageLevel(MESSAGE_NOTHING);
36 36
  }
37 37

	
38 38
  ClpLp::~ClpLp() {
39 39
    delete _prob;
40 40
    _clear_temporals();
41 41
  }
42 42

	
43 43
  void ClpLp::_init_temporals() {
44 44
    _primal_ray = 0;
45 45
    _dual_ray = 0;
46 46
  }
47 47

	
48 48
  void ClpLp::_clear_temporals() {
49 49
    if (_primal_ray) {
50 50
      delete[] _primal_ray;
51 51
      _primal_ray = 0;
52 52
    }
53 53
    if (_dual_ray) {
54 54
      delete[] _dual_ray;
55 55
      _dual_ray = 0;
56 56
    }
57 57
  }
58 58

	
59 59
  ClpLp* ClpLp::newSolver() const {
60 60
    ClpLp* newlp = new ClpLp;
61 61
    return newlp;
62 62
  }
63 63

	
64 64
  ClpLp* ClpLp::cloneSolver() const {
65 65
    ClpLp* copylp = new ClpLp(*this);
66 66
    return copylp;
67 67
  }
68 68

	
69 69
  const char* ClpLp::_solverName() const { return "ClpLp"; }
70 70

	
71 71
  int ClpLp::_addCol() {
72 72
    _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
73 73
    return _prob->numberColumns() - 1;
74 74
  }
75 75

	
76 76
  int ClpLp::_addRow() {
77 77
    _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
78 78
    return _prob->numberRows() - 1;
79 79
  }
80 80

	
81 81

	
82 82
  void ClpLp::_eraseCol(int c) {
83 83
    _col_names_ref.erase(_prob->getColumnName(c));
... ...
@@ -385,53 +385,69 @@
385 385
    } else if (_prob->isProvenDualInfeasible()) {
386 386
      return UNBOUNDED;
387 387
    } else {
388 388
      return UNDEFINED;
389 389
    }
390 390
  }
391 391

	
392 392
  ClpLp::ProblemType ClpLp::_getDualType() const {
393 393
    if (_prob->isProvenOptimal()) {
394 394
      return OPTIMAL;
395 395
    } else if (_prob->isProvenDualInfeasible()) {
396 396
      return INFEASIBLE;
397 397
    } else if (_prob->isProvenPrimalInfeasible()) {
398 398
      return INFEASIBLE;
399 399
    } else {
400 400
      return UNDEFINED;
401 401
    }
402 402
  }
403 403

	
404 404
  void ClpLp::_setSense(ClpLp::Sense sense) {
405 405
    switch (sense) {
406 406
    case MIN:
407 407
      _prob->setOptimizationDirection(1);
408 408
      break;
409 409
    case MAX:
410 410
      _prob->setOptimizationDirection(-1);
411 411
      break;
412 412
    }
413 413
  }
414 414

	
415 415
  ClpLp::Sense ClpLp::_getSense() const {
416 416
    double dir = _prob->optimizationDirection();
417 417
    if (dir > 0.0) {
418 418
      return MIN;
419 419
    } else {
420 420
      return MAX;
421 421
    }
422 422
  }
423 423

	
424 424
  void ClpLp::_clear() {
425 425
    delete _prob;
426 426
    _prob = new ClpSimplex();
427 427
    rows.clear();
428 428
    cols.clear();
429 429
    _col_names_ref.clear();
430 430
    _clear_temporals();
431 431
  }
432 432

	
433
  void ClpLp::messageLevel(MessageLevel m) {
434
    _prob->setLogLevel(static_cast<int>(m));
433
  void ClpLp::_messageLevel(MessageLevel level) {
434
    switch (level) {
435
    case MESSAGE_NOTHING:
436
      _prob->setLogLevel(0);
437
      break;
438
    case MESSAGE_ERROR:
439
      _prob->setLogLevel(1);
440
      break;
441
    case MESSAGE_WARNING:
442
      _prob->setLogLevel(2);
443
      break;
444
    case MESSAGE_NORMAL:
445
      _prob->setLogLevel(3);
446
      break;
447
    case MESSAGE_VERBOSE:
448
      _prob->setLogLevel(4);
449
      break;
450
    }
435 451
  }
436 452

	
437 453
} //END OF NAMESPACE LEMON
Ignore white space 6 line context
... ...
@@ -91,91 +91,73 @@
91 91
    virtual int _rowByName(const std::string& name) const;
92 92

	
93 93
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
94 94
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
95 95

	
96 96
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
97 97
    virtual void _getColCoeffs(int i, InsertIterator b) const;
98 98

	
99 99
    virtual void _setCoeff(int row, int col, Value value);
100 100
    virtual Value _getCoeff(int row, int col) const;
101 101

	
102 102
    virtual void _setColLowerBound(int i, Value value);
103 103
    virtual Value _getColLowerBound(int i) const;
104 104
    virtual void _setColUpperBound(int i, Value value);
105 105
    virtual Value _getColUpperBound(int i) const;
106 106

	
107 107
    virtual void _setRowLowerBound(int i, Value value);
108 108
    virtual Value _getRowLowerBound(int i) const;
109 109
    virtual void _setRowUpperBound(int i, Value value);
110 110
    virtual Value _getRowUpperBound(int i) const;
111 111

	
112 112
    virtual void _setObjCoeffs(ExprIterator, ExprIterator);
113 113
    virtual void _getObjCoeffs(InsertIterator) const;
114 114

	
115 115
    virtual void _setObjCoeff(int i, Value obj_coef);
116 116
    virtual Value _getObjCoeff(int i) const;
117 117

	
118 118
    virtual void _setSense(Sense sense);
119 119
    virtual Sense _getSense() const;
120 120

	
121 121
    virtual SolveExitStatus _solve();
122 122

	
123 123
    virtual Value _getPrimal(int i) const;
124 124
    virtual Value _getDual(int i) const;
125 125

	
126 126
    virtual Value _getPrimalValue() const;
127 127

	
128 128
    virtual Value _getPrimalRay(int i) const;
129 129
    virtual Value _getDualRay(int i) const;
130 130

	
131 131
    virtual VarStatus _getColStatus(int i) const;
132 132
    virtual VarStatus _getRowStatus(int i) const;
133 133

	
134 134
    virtual ProblemType _getPrimalType() const;
135 135
    virtual ProblemType _getDualType() const;
136 136

	
137 137
    virtual void _clear();
138 138

	
139
    virtual void _messageLevel(MessageLevel);
140
    
139 141
  public:
140 142

	
141 143
    ///Solves LP with primal simplex method.
142 144
    SolveExitStatus solvePrimal();
143 145

	
144 146
    ///Solves LP with dual simplex method.
145 147
    SolveExitStatus solveDual();
146 148

	
147 149
    ///Solves LP with barrier method.
148 150
    SolveExitStatus solveBarrier();
149 151

	
150 152
    ///Returns the constraint identifier understood by CLP.
151 153
    int clpRow(Row r) const { return rows(id(r)); }
152 154

	
153 155
    ///Returns the variable identifier understood by CLP.
154 156
    int clpCol(Col c) const { return cols(id(c)); }
155 157

	
156
    ///Enum for \c messageLevel() parameter
157
    enum MessageLevel {
158
      /// no output (default value)
159
      MESSAGE_NO_OUTPUT = 0,
160
      /// print final solution
161
      MESSAGE_FINAL_SOLUTION = 1,
162
      /// print factorization
163
      MESSAGE_FACTORIZATION = 2,
164
      /// normal output
165
      MESSAGE_NORMAL_OUTPUT = 3,
166
      /// verbose output
167
      MESSAGE_VERBOSE_OUTPUT = 4
168
    };
169
    ///Set the verbosity of the messages
170

	
171
    ///Set the verbosity of the messages
172
    ///
173
    ///\param m is the level of the messages output by the solver routines.
174
    void messageLevel(MessageLevel m);
175

	
176 158
  };
177 159

	
178 160
} //END OF NAMESPACE LEMON
179 161

	
180 162
#endif //LEMON_CLP_H
181 163

	
Ignore white space 6 line context
... ...
@@ -27,110 +27,113 @@
27 27
}
28 28

	
29 29

	
30 30
///\file
31 31
///\brief Implementation of the LEMON-CPLEX lp solver interface.
32 32
namespace lemon {
33 33

	
34 34
  CplexEnv::LicenseError::LicenseError(int status) {
35 35
    if (!CPXgeterrorstring(0, status, _message)) {
36 36
      std::strcpy(_message, "Cplex unknown error");
37 37
    }
38 38
  }
39 39

	
40 40
  CplexEnv::CplexEnv() {
41 41
    int status;
42 42
    _cnt = new int;
43 43
    _env = CPXopenCPLEX(&status);
44 44
    if (_env == 0) {
45 45
      delete _cnt;
46 46
      _cnt = 0;
47 47
      throw LicenseError(status);
48 48
    }
49 49
  }
50 50

	
51 51
  CplexEnv::CplexEnv(const CplexEnv& other) {
52 52
    _env = other._env;
53 53
    _cnt = other._cnt;
54 54
    ++(*_cnt);
55 55
  }
56 56

	
57 57
  CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
58 58
    _env = other._env;
59 59
    _cnt = other._cnt;
60 60
    ++(*_cnt);
61 61
    return *this;
62 62
  }
63 63

	
64 64
  CplexEnv::~CplexEnv() {
65 65
    --(*_cnt);
66 66
    if (*_cnt == 0) {
67 67
      delete _cnt;
68 68
      CPXcloseCPLEX(&_env);
69 69
    }
70 70
  }
71 71

	
72 72
  CplexBase::CplexBase() : LpBase() {
73 73
    int status;
74 74
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
75
    messageLevel(MESSAGE_NOTHING);
75 76
  }
76 77

	
77 78
  CplexBase::CplexBase(const CplexEnv& env)
78 79
    : LpBase(), _env(env) {
79 80
    int status;
80 81
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
82
    messageLevel(MESSAGE_NOTHING);
81 83
  }
82 84

	
83 85
  CplexBase::CplexBase(const CplexBase& cplex)
84 86
    : LpBase() {
85 87
    int status;
86 88
    _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
87 89
    rows = cplex.rows;
88 90
    cols = cplex.cols;
91
    messageLevel(MESSAGE_NOTHING);
89 92
  }
90 93

	
91 94
  CplexBase::~CplexBase() {
92 95
    CPXfreeprob(cplexEnv(),&_prob);
93 96
  }
94 97

	
95 98
  int CplexBase::_addCol() {
96 99
    int i = CPXgetnumcols(cplexEnv(), _prob);
97 100
    double lb = -INF, ub = INF;
98 101
    CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
99 102
    return i;
100 103
  }
101 104

	
102 105

	
103 106
  int CplexBase::_addRow() {
104 107
    int i = CPXgetnumrows(cplexEnv(), _prob);
105 108
    const double ub = INF;
106 109
    const char s = 'L';
107 110
    CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
108 111
    return i;
109 112
  }
110 113

	
111 114

	
112 115
  void CplexBase::_eraseCol(int i) {
113 116
    CPXdelcols(cplexEnv(), _prob, i, i);
114 117
  }
115 118

	
116 119
  void CplexBase::_eraseRow(int i) {
117 120
    CPXdelrows(cplexEnv(), _prob, i, i);
118 121
  }
119 122

	
120 123
  void CplexBase::_eraseColId(int i) {
121 124
    cols.eraseIndex(i);
122 125
    cols.shiftIndices(i);
123 126
  }
124 127
  void CplexBase::_eraseRowId(int i) {
125 128
    rows.eraseIndex(i);
126 129
    rows.shiftIndices(i);
127 130
  }
128 131

	
129 132
  void CplexBase::_getColName(int col, std::string &name) const {
130 133
    int size;
131 134
    CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
132 135
    if (size == 0) {
133 136
      name.clear();
134 137
      return;
135 138
    }
136 139

	
... ...
@@ -393,410 +396,432 @@
393 396
        ++b;
394 397
      }
395 398
    }
396 399
  }
397 400

	
398 401
  void CplexBase::_setObjCoeff(int i, Value obj_coef)
399 402
  {
400 403
    CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
401 404
  }
402 405

	
403 406
  CplexBase::Value CplexBase::_getObjCoeff(int i) const
404 407
  {
405 408
    Value x;
406 409
    CPXgetobj(cplexEnv(), _prob, &x, i, i);
407 410
    return x;
408 411
  }
409 412

	
410 413
  void CplexBase::_setSense(CplexBase::Sense sense) {
411 414
    switch (sense) {
412 415
    case MIN:
413 416
      CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
414 417
      break;
415 418
    case MAX:
416 419
      CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
417 420
      break;
418 421
    }
419 422
  }
420 423

	
421 424
  CplexBase::Sense CplexBase::_getSense() const {
422 425
    switch (CPXgetobjsen(cplexEnv(), _prob)) {
423 426
    case CPX_MIN:
424 427
      return MIN;
425 428
    case CPX_MAX:
426 429
      return MAX;
427 430
    default:
428 431
      LEMON_ASSERT(false, "Invalid sense");
429 432
      return CplexBase::Sense();
430 433
    }
431 434
  }
432 435

	
433 436
  void CplexBase::_clear() {
434 437
    CPXfreeprob(cplexEnv(),&_prob);
435 438
    int status;
436 439
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
437 440
    rows.clear();
438 441
    cols.clear();
439 442
  }
440 443

	
444
  void CplexBase::_messageLevel(MessageLevel level) {
445
    switch (level) {
446
    case MESSAGE_NOTHING:
447
      _message_enabled = false;
448
      break;
449
    case MESSAGE_ERROR:
450
    case MESSAGE_WARNING:
451
    case MESSAGE_NORMAL:
452
    case MESSAGE_VERBOSE:
453
      _message_enabled = true;
454
      break;
455
    }
456
  }
457

	
458
  void CplexBase::_applyMessageLevel() {
459
    CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND, 
460
                   _message_enabled ? CPX_ON : CPX_OFF);
461
  }
462

	
441 463
  // CplexLp members
442 464

	
443 465
  CplexLp::CplexLp()
444 466
    : LpBase(), LpSolver(), CplexBase() {}
445 467

	
446 468
  CplexLp::CplexLp(const CplexEnv& env)
447 469
    : LpBase(), LpSolver(), CplexBase(env) {}
448 470

	
449 471
  CplexLp::CplexLp(const CplexLp& other)
450 472
    : LpBase(), LpSolver(), CplexBase(other) {}
451 473

	
452 474
  CplexLp::~CplexLp() {}
453 475

	
454 476
  CplexLp* CplexLp::newSolver() const { return new CplexLp; }
455 477
  CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
456 478

	
457 479
  const char* CplexLp::_solverName() const { return "CplexLp"; }
458 480

	
459 481
  void CplexLp::_clear_temporals() {
460 482
    _col_status.clear();
461 483
    _row_status.clear();
462 484
    _primal_ray.clear();
463 485
    _dual_ray.clear();
464 486
  }
465 487

	
466 488
  // The routine returns zero unless an error occurred during the
467 489
  // optimization. Examples of errors include exhausting available
468 490
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
469 491
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
470 492
  // user-specified CPLEX limit, or proving the model infeasible or
471 493
  // unbounded, are not considered errors. Note that a zero return
472 494
  // value does not necessarily mean that a solution exists. Use query
473 495
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
474 496
  // further information about the status of the optimization.
475 497
  CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
476 498
#if CPX_VERSION >= 800
477 499
    if (status == 0) {
478 500
      switch (CPXgetstat(cplexEnv(), _prob)) {
479 501
      case CPX_STAT_OPTIMAL:
480 502
      case CPX_STAT_INFEASIBLE:
481 503
      case CPX_STAT_UNBOUNDED:
482 504
        return SOLVED;
483 505
      default:
484 506
        return UNSOLVED;
485 507
      }
486 508
    } else {
487 509
      return UNSOLVED;
488 510
    }
489 511
#else
490 512
    if (status == 0) {
491 513
      //We want to exclude some cases
492 514
      switch (CPXgetstat(cplexEnv(), _prob)) {
493 515
      case CPX_OBJ_LIM:
494 516
      case CPX_IT_LIM_FEAS:
495 517
      case CPX_IT_LIM_INFEAS:
496 518
      case CPX_TIME_LIM_FEAS:
497 519
      case CPX_TIME_LIM_INFEAS:
498 520
        return UNSOLVED;
499 521
      default:
500 522
        return SOLVED;
501 523
      }
502 524
    } else {
503 525
      return UNSOLVED;
504 526
    }
505 527
#endif
506 528
  }
507 529

	
508 530
  CplexLp::SolveExitStatus CplexLp::_solve() {
509 531
    _clear_temporals();
532
    _applyMessageLevel();
510 533
    return convertStatus(CPXlpopt(cplexEnv(), _prob));
511 534
  }
512 535

	
513 536
  CplexLp::SolveExitStatus CplexLp::solvePrimal() {
514 537
    _clear_temporals();
538
    _applyMessageLevel();
515 539
    return convertStatus(CPXprimopt(cplexEnv(), _prob));
516 540
  }
517 541

	
518 542
  CplexLp::SolveExitStatus CplexLp::solveDual() {
519 543
    _clear_temporals();
544
    _applyMessageLevel();
520 545
    return convertStatus(CPXdualopt(cplexEnv(), _prob));
521 546
  }
522 547

	
523 548
  CplexLp::SolveExitStatus CplexLp::solveBarrier() {
524 549
    _clear_temporals();
550
    _applyMessageLevel();
525 551
    return convertStatus(CPXbaropt(cplexEnv(), _prob));
526 552
  }
527 553

	
528 554
  CplexLp::Value CplexLp::_getPrimal(int i) const {
529 555
    Value x;
530 556
    CPXgetx(cplexEnv(), _prob, &x, i, i);
531 557
    return x;
532 558
  }
533 559

	
534 560
  CplexLp::Value CplexLp::_getDual(int i) const {
535 561
    Value y;
536 562
    CPXgetpi(cplexEnv(), _prob, &y, i, i);
537 563
    return y;
538 564
  }
539 565

	
540 566
  CplexLp::Value CplexLp::_getPrimalValue() const {
541 567
    Value objval;
542 568
    CPXgetobjval(cplexEnv(), _prob, &objval);
543 569
    return objval;
544 570
  }
545 571

	
546 572
  CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
547 573
    if (_col_status.empty()) {
548 574
      _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
549 575
      CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
550 576
    }
551 577
    switch (_col_status[i]) {
552 578
    case CPX_BASIC:
553 579
      return BASIC;
554 580
    case CPX_FREE_SUPER:
555 581
      return FREE;
556 582
    case CPX_AT_LOWER:
557 583
      return LOWER;
558 584
    case CPX_AT_UPPER:
559 585
      return UPPER;
560 586
    default:
561 587
      LEMON_ASSERT(false, "Wrong column status");
562 588
      return CplexLp::VarStatus();
563 589
    }
564 590
  }
565 591

	
566 592
  CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
567 593
    if (_row_status.empty()) {
568 594
      _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
569 595
      CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
570 596
    }
571 597
    switch (_row_status[i]) {
572 598
    case CPX_BASIC:
573 599
      return BASIC;
574 600
    case CPX_AT_LOWER:
575 601
      {
576 602
        char s;
577 603
        CPXgetsense(cplexEnv(), _prob, &s, i, i);
578 604
        return s != 'L' ? LOWER : UPPER;
579 605
      }
580 606
    case CPX_AT_UPPER:
581 607
      return UPPER;
582 608
    default:
583 609
      LEMON_ASSERT(false, "Wrong row status");
584 610
      return CplexLp::VarStatus();
585 611
    }
586 612
  }
587 613

	
588 614
  CplexLp::Value CplexLp::_getPrimalRay(int i) const {
589 615
    if (_primal_ray.empty()) {
590 616
      _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
591 617
      CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
592 618
    }
593 619
    return _primal_ray[i];
594 620
  }
595 621

	
596 622
  CplexLp::Value CplexLp::_getDualRay(int i) const {
597 623
    if (_dual_ray.empty()) {
598 624

	
599 625
    }
600 626
    return _dual_ray[i];
601 627
  }
602 628

	
603
  //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
629
  // Cplex 7.0 status values
604 630
  // This table lists the statuses, returned by the CPXgetstat()
605 631
  // routine, for solutions to LP problems or mixed integer problems. If
606 632
  // no solution exists, the return value is zero.
607 633

	
608 634
  // For Simplex, Barrier
609 635
  // 1          CPX_OPTIMAL
610 636
  //          Optimal solution found
611 637
  // 2          CPX_INFEASIBLE
612 638
  //          Problem infeasible
613 639
  // 3    CPX_UNBOUNDED
614 640
  //          Problem unbounded
615 641
  // 4          CPX_OBJ_LIM
616 642
  //          Objective limit exceeded in Phase II
617 643
  // 5          CPX_IT_LIM_FEAS
618 644
  //          Iteration limit exceeded in Phase II
619 645
  // 6          CPX_IT_LIM_INFEAS
620 646
  //          Iteration limit exceeded in Phase I
621 647
  // 7          CPX_TIME_LIM_FEAS
622 648
  //          Time limit exceeded in Phase II
623 649
  // 8          CPX_TIME_LIM_INFEAS
624 650
  //          Time limit exceeded in Phase I
625 651
  // 9          CPX_NUM_BEST_FEAS
626 652
  //          Problem non-optimal, singularities in Phase II
627 653
  // 10         CPX_NUM_BEST_INFEAS
628 654
  //          Problem non-optimal, singularities in Phase I
629 655
  // 11         CPX_OPTIMAL_INFEAS
630 656
  //          Optimal solution found, unscaled infeasibilities
631 657
  // 12         CPX_ABORT_FEAS
632 658
  //          Aborted in Phase II
633 659
  // 13         CPX_ABORT_INFEAS
634 660
  //          Aborted in Phase I
635 661
  // 14          CPX_ABORT_DUAL_INFEAS
636 662
  //          Aborted in barrier, dual infeasible
637 663
  // 15          CPX_ABORT_PRIM_INFEAS
638 664
  //          Aborted in barrier, primal infeasible
639 665
  // 16          CPX_ABORT_PRIM_DUAL_INFEAS
640 666
  //          Aborted in barrier, primal and dual infeasible
641 667
  // 17          CPX_ABORT_PRIM_DUAL_FEAS
642 668
  //          Aborted in barrier, primal and dual feasible
643 669
  // 18          CPX_ABORT_CROSSOVER
644 670
  //          Aborted in crossover
645 671
  // 19          CPX_INForUNBD
646 672
  //          Infeasible or unbounded
647 673
  // 20   CPX_PIVOT
648 674
  //       User pivot used
649 675
  //
650
  //     Ezeket hova tegyem:
676
  // Pending return values
651 677
  // ??case CPX_ABORT_DUAL_INFEAS
652 678
  // ??case CPX_ABORT_CROSSOVER
653 679
  // ??case CPX_INForUNBD
654 680
  // ??case CPX_PIVOT
655 681

	
656 682
  //Some more interesting stuff:
657 683

	
658 684
  // CPX_PARAM_PROBMETHOD  1062  int  LPMETHOD
659 685
  // 0 Automatic
660 686
  // 1 Primal Simplex
661 687
  // 2 Dual Simplex
662 688
  // 3 Network Simplex
663 689
  // 4 Standard Barrier
664 690
  // Default: 0
665 691
  // Description: Method for linear optimization.
666 692
  // Determines which algorithm is used when CPXlpopt() (or "optimize"
667 693
  // in the Interactive Optimizer) is called. Currently the behavior of
668 694
  // the "Automatic" setting is that CPLEX simply invokes the dual
669 695
  // simplex method, but this capability may be expanded in the future
670 696
  // so that CPLEX chooses the method based on problem characteristics
671 697
#if CPX_VERSION < 900
672 698
  void statusSwitch(CPXENVptr cplexEnv(),int& stat){
673 699
    int lpmethod;
674 700
    CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
675 701
    if (lpmethod==2){
676 702
      if (stat==CPX_UNBOUNDED){
677 703
        stat=CPX_INFEASIBLE;
678 704
      }
679 705
      else{
680 706
        if (stat==CPX_INFEASIBLE)
681 707
          stat=CPX_UNBOUNDED;
682 708
      }
683 709
    }
684 710
  }
685 711
#else
686 712
  void statusSwitch(CPXENVptr,int&){}
687 713
#endif
688 714

	
689 715
  CplexLp::ProblemType CplexLp::_getPrimalType() const {
690 716
    // Unboundedness not treated well: the following is from cplex 9.0 doc
691 717
    // About Unboundedness
692 718

	
693 719
    // The treatment of models that are unbounded involves a few
694 720
    // subtleties. Specifically, a declaration of unboundedness means that
695 721
    // ILOG CPLEX has determined that the model has an unbounded
696 722
    // ray. Given any feasible solution x with objective z, a multiple of
697 723
    // the unbounded ray can be added to x to give a feasible solution
698 724
    // with objective z-1 (or z+1 for maximization models). Thus, if a
699 725
    // feasible solution exists, then the optimal objective is
700 726
    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
701 727
    // a feasible solution exists. Users can call the routine CPXsolninfo
702 728
    // to determine whether ILOG CPLEX has also concluded that the model
703 729
    // has a feasible solution.
704 730

	
705 731
    int stat = CPXgetstat(cplexEnv(), _prob);
706 732
#if CPX_VERSION >= 800
707 733
    switch (stat)
708 734
      {
709 735
      case CPX_STAT_OPTIMAL:
710 736
        return OPTIMAL;
711 737
      case CPX_STAT_UNBOUNDED:
712 738
        return UNBOUNDED;
713 739
      case CPX_STAT_INFEASIBLE:
714 740
        return INFEASIBLE;
715 741
      default:
716 742
        return UNDEFINED;
717 743
      }
718 744
#else
719 745
    statusSwitch(cplexEnv(),stat);
720 746
    //CPXgetstat(cplexEnv(), _prob);
721
    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
722 747
    switch (stat) {
723 748
    case 0:
724 749
      return UNDEFINED; //Undefined
725 750
    case CPX_OPTIMAL://Optimal
726 751
      return OPTIMAL;
727 752
    case CPX_UNBOUNDED://Unbounded
728 753
      return INFEASIBLE;//In case of dual simplex
729 754
      //return UNBOUNDED;
730 755
    case CPX_INFEASIBLE://Infeasible
731 756
      //    case CPX_IT_LIM_INFEAS:
732 757
      //     case CPX_TIME_LIM_INFEAS:
733 758
      //     case CPX_NUM_BEST_INFEAS:
734 759
      //     case CPX_OPTIMAL_INFEAS:
735 760
      //     case CPX_ABORT_INFEAS:
736 761
      //     case CPX_ABORT_PRIM_INFEAS:
737 762
      //     case CPX_ABORT_PRIM_DUAL_INFEAS:
738 763
      return UNBOUNDED;//In case of dual simplex
739 764
      //return INFEASIBLE;
740 765
      //     case CPX_OBJ_LIM:
741 766
      //     case CPX_IT_LIM_FEAS:
742 767
      //     case CPX_TIME_LIM_FEAS:
743 768
      //     case CPX_NUM_BEST_FEAS:
744 769
      //     case CPX_ABORT_FEAS:
745 770
      //     case CPX_ABORT_PRIM_DUAL_FEAS:
746 771
      //       return FEASIBLE;
747 772
    default:
748 773
      return UNDEFINED; //Everything else comes here
749 774
      //FIXME error
750 775
    }
751 776
#endif
752 777
  }
753 778

	
754
  //9.0-as cplex verzio statusai
779
  // Cplex 9.0 status values
755 780
  // CPX_STAT_ABORT_DUAL_OBJ_LIM
756 781
  // CPX_STAT_ABORT_IT_LIM
757 782
  // CPX_STAT_ABORT_OBJ_LIM
758 783
  // CPX_STAT_ABORT_PRIM_OBJ_LIM
759 784
  // CPX_STAT_ABORT_TIME_LIM
760 785
  // CPX_STAT_ABORT_USER
761 786
  // CPX_STAT_FEASIBLE_RELAXED
762 787
  // CPX_STAT_INFEASIBLE
763 788
  // CPX_STAT_INForUNBD
764 789
  // CPX_STAT_NUM_BEST
765 790
  // CPX_STAT_OPTIMAL
766 791
  // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
767 792
  // CPX_STAT_OPTIMAL_INFEAS
768 793
  // CPX_STAT_OPTIMAL_RELAXED
769 794
  // CPX_STAT_UNBOUNDED
770 795

	
771 796
  CplexLp::ProblemType CplexLp::_getDualType() const {
772 797
    int stat = CPXgetstat(cplexEnv(), _prob);
773 798
#if CPX_VERSION >= 800
774 799
    switch (stat) {
775 800
    case CPX_STAT_OPTIMAL:
776 801
      return OPTIMAL;
777 802
    case CPX_STAT_UNBOUNDED:
778 803
      return INFEASIBLE;
779 804
    default:
780 805
      return UNDEFINED;
781 806
    }
782 807
#else
783 808
    statusSwitch(cplexEnv(),stat);
784 809
    switch (stat) {
785 810
    case 0:
786 811
      return UNDEFINED; //Undefined
787 812
    case CPX_OPTIMAL://Optimal
788 813
      return OPTIMAL;
789 814
    case CPX_UNBOUNDED:
790 815
      return INFEASIBLE;
791 816
    default:
792 817
      return UNDEFINED; //Everything else comes here
793 818
      //FIXME error
794 819
    }
795 820
#endif
796 821
  }
797 822

	
798 823
  // CplexMip members
799 824

	
800 825
  CplexMip::CplexMip()
801 826
    : LpBase(), MipSolver(), CplexBase() {
802 827

	
... ...
@@ -819,96 +844,97 @@
819 844
  }
820 845

	
821 846
  CplexMip::CplexMip(const CplexMip& other)
822 847
    : LpBase(), MipSolver(), CplexBase(other) {}
823 848

	
824 849
  CplexMip::~CplexMip() {}
825 850

	
826 851
  CplexMip* CplexMip::newSolver() const { return new CplexMip; }
827 852
  CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
828 853

	
829 854
  const char* CplexMip::_solverName() const { return "CplexMip"; }
830 855

	
831 856
  void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
832 857

	
833 858
    // Note If a variable is to be changed to binary, a call to CPXchgbds
834 859
    // should also be made to change the bounds to 0 and 1.
835 860

	
836 861
    switch (col_type){
837 862
    case INTEGER: {
838 863
      const char t = 'I';
839 864
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
840 865
    } break;
841 866
    case REAL: {
842 867
      const char t = 'C';
843 868
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
844 869
    } break;
845 870
    default:
846 871
      break;
847 872
    }
848 873
  }
849 874

	
850 875
  CplexMip::ColTypes CplexMip::_getColType(int i) const {
851 876
    char t;
852 877
    CPXgetctype (cplexEnv(), _prob, &t, i, i);
853 878
    switch (t) {
854 879
    case 'I':
855 880
      return INTEGER;
856 881
    case 'C':
857 882
      return REAL;
858 883
    default:
859 884
      LEMON_ASSERT(false, "Invalid column type");
860 885
      return ColTypes();
861 886
    }
862 887

	
863 888
  }
864 889

	
865 890
  CplexMip::SolveExitStatus CplexMip::_solve() {
866 891
    int status;
892
    _applyMessageLevel();
867 893
    status = CPXmipopt (cplexEnv(), _prob);
868 894
    if (status==0)
869 895
      return SOLVED;
870 896
    else
871 897
      return UNSOLVED;
872 898

	
873 899
  }
874 900

	
875 901

	
876 902
  CplexMip::ProblemType CplexMip::_getType() const {
877 903

	
878 904
    int stat = CPXgetstat(cplexEnv(), _prob);
879 905

	
880 906
    //Fortunately, MIP statuses did not change for cplex 8.0
881 907
    switch (stat) {
882 908
    case CPXMIP_OPTIMAL:
883 909
      // Optimal integer solution has been found.
884 910
    case CPXMIP_OPTIMAL_TOL:
885 911
      // Optimal soluton with the tolerance defined by epgap or epagap has
886 912
      // been found.
887 913
      return OPTIMAL;
888 914
      //This also exists in later issues
889 915
      //    case CPXMIP_UNBOUNDED:
890 916
      //return UNBOUNDED;
891 917
      case CPXMIP_INFEASIBLE:
892 918
        return INFEASIBLE;
893 919
    default:
894 920
      return UNDEFINED;
895 921
    }
896 922
    //Unboundedness not treated well: the following is from cplex 9.0 doc
897 923
    // About Unboundedness
898 924

	
899 925
    // The treatment of models that are unbounded involves a few
900 926
    // subtleties. Specifically, a declaration of unboundedness means that
901 927
    // ILOG CPLEX has determined that the model has an unbounded
902 928
    // ray. Given any feasible solution x with objective z, a multiple of
903 929
    // the unbounded ray can be added to x to give a feasible solution
904 930
    // with objective z-1 (or z+1 for maximization models). Thus, if a
905 931
    // feasible solution exists, then the optimal objective is
906 932
    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
907 933
    // a feasible solution exists. Users can call the routine CPXsolninfo
908 934
    // to determine whether ILOG CPLEX has also concluded that the model
909 935
    // has a feasible solution.
910 936
  }
911 937

	
912 938
  CplexMip::Value CplexMip::_getSol(int i) const {
913 939
    Value x;
914 940
    CPXgetmipx(cplexEnv(), _prob, &x, i, i);
Ignore white space 6 line context
... ...
@@ -99,104 +99,119 @@
99 99

	
100 100
    virtual void _eraseColId(int i);
101 101
    virtual void _eraseRowId(int i);
102 102

	
103 103
    virtual void _getColName(int col, std::string& name) const;
104 104
    virtual void _setColName(int col, const std::string& name);
105 105
    virtual int _colByName(const std::string& name) const;
106 106

	
107 107
    virtual void _getRowName(int row, std::string& name) const;
108 108
    virtual void _setRowName(int row, const std::string& name);
109 109
    virtual int _rowByName(const std::string& name) const;
110 110

	
111 111
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
112 112
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
113 113

	
114 114
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
115 115
    virtual void _getColCoeffs(int i, InsertIterator b) const;
116 116

	
117 117
    virtual void _setCoeff(int row, int col, Value value);
118 118
    virtual Value _getCoeff(int row, int col) const;
119 119

	
120 120
    virtual void _setColLowerBound(int i, Value value);
121 121
    virtual Value _getColLowerBound(int i) const;
122 122

	
123 123
    virtual void _setColUpperBound(int i, Value value);
124 124
    virtual Value _getColUpperBound(int i) const;
125 125

	
126 126
  private:
127 127
    void _set_row_bounds(int i, Value lb, Value ub);
128 128
  protected:
129 129

	
130 130
    virtual void _setRowLowerBound(int i, Value value);
131 131
    virtual Value _getRowLowerBound(int i) const;
132 132

	
133 133
    virtual void _setRowUpperBound(int i, Value value);
134 134
    virtual Value _getRowUpperBound(int i) const;
135 135

	
136 136
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
137 137
    virtual void _getObjCoeffs(InsertIterator b) const;
138 138

	
139 139
    virtual void _setObjCoeff(int i, Value obj_coef);
140 140
    virtual Value _getObjCoeff(int i) const;
141 141

	
142 142
    virtual void _setSense(Sense sense);
143 143
    virtual Sense _getSense() const;
144 144

	
145 145
    virtual void _clear();
146 146

	
147
    virtual void _messageLevel(MessageLevel level);
148
    void _applyMessageLevel();
149

	
150
    bool _message_enabled;
151

	
147 152
  public:
148 153

	
149 154
    /// Returns the used \c CplexEnv instance
150 155
    const CplexEnv& env() const { return _env; }
156

	
157
    /// \brief Returns the const cpxenv pointer
151 158
    ///
159
    /// \note The cpxenv might be destructed with the solver.
152 160
    const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
153 161

	
162
    /// \brief Returns the const cpxenv pointer
163
    ///
164
    /// \note The cpxenv might be destructed with the solver.
165
    cpxenv* cplexEnv() { return _env.cplexEnv(); }
166

	
167
    /// Returns the cplex problem object
154 168
    cpxlp* cplexLp() { return _prob; }
169
    /// Returns the cplex problem object
155 170
    const cpxlp* cplexLp() const { return _prob; }
156 171

	
157 172
  };
158 173

	
159 174
  /// \brief Interface for the CPLEX LP solver
160 175
  ///
161 176
  /// This class implements an interface for the CPLEX LP solver.
162 177
  ///\ingroup lp_group
163 178
  class CplexLp : public LpSolver, public CplexBase {
164 179
  public:
165 180
    /// \e
166 181
    CplexLp();
167 182
    /// \e
168 183
    CplexLp(const CplexEnv&);
169 184
    /// \e
170 185
    CplexLp(const CplexLp&);
171 186
    /// \e
172 187
    virtual ~CplexLp();
173 188

	
174 189
    /// \e
175 190
    virtual CplexLp* cloneSolver() const;
176 191
    /// \e
177 192
    virtual CplexLp* newSolver() const;
178 193

	
179 194
  private:
180 195

	
181 196
    // these values cannot retrieved element by element
182 197
    mutable std::vector<int> _col_status;
183 198
    mutable std::vector<int> _row_status;
184 199

	
185 200
    mutable std::vector<Value> _primal_ray;
186 201
    mutable std::vector<Value> _dual_ray;
187 202

	
188 203
    void _clear_temporals();
189 204

	
190 205
    SolveExitStatus convertStatus(int status);
191 206

	
192 207
  protected:
193 208

	
194 209
    virtual const char* _solverName() const;
195 210

	
196 211
    virtual SolveExitStatus _solve();
197 212
    virtual Value _getPrimal(int i) const;
198 213
    virtual Value _getDual(int i) const;
199 214
    virtual Value _getPrimalValue() const;
200 215

	
201 216
    virtual VarStatus _getColStatus(int i) const;
202 217
    virtual VarStatus _getRowStatus(int i) const;
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\file
20 20
///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
21 21

	
22 22
#include <lemon/glpk.h>
23 23
#include <glpk.h>
24 24

	
25 25
#include <lemon/assert.h>
26 26

	
27 27
namespace lemon {
28 28

	
29 29
  // GlpkBase members
30 30

	
31 31
  GlpkBase::GlpkBase() : LpBase() {
32 32
    lp = glp_create_prob();
33 33
    glp_create_index(lp);
34
    messageLevel(MESSAGE_NOTHING);
34 35
  }
35 36

	
36 37
  GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
37 38
    lp = glp_create_prob();
38 39
    glp_copy_prob(lp, other.lp, GLP_ON);
39 40
    glp_create_index(lp);
40 41
    rows = other.rows;
41 42
    cols = other.cols;
43
    messageLevel(MESSAGE_NOTHING);
42 44
  }
43 45

	
44 46
  GlpkBase::~GlpkBase() {
45 47
    glp_delete_prob(lp);
46 48
  }
47 49

	
48 50
  int GlpkBase::_addCol() {
49 51
    int i = glp_add_cols(lp, 1);
50 52
    glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
51 53
    return i;
52 54
  }
53 55

	
54 56
  int GlpkBase::_addRow() {
55 57
    int i = glp_add_rows(lp, 1);
56 58
    glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
57 59
    return i;
58 60
  }
59 61

	
60 62
  void GlpkBase::_eraseCol(int i) {
61 63
    int ca[2];
62 64
    ca[1] = i;
63 65
    glp_del_cols(lp, 1, ca);
64 66
  }
65 67

	
66 68
  void GlpkBase::_eraseRow(int i) {
67 69
    int ra[2];
68 70
    ra[1] = i;
69 71
    glp_del_rows(lp, 1, ra);
70 72
  }
71 73

	
72 74
  void GlpkBase::_eraseColId(int i) {
73 75
    cols.eraseIndex(i);
74 76
    cols.shiftIndices(i);
75 77
  }
76 78

	
77 79
  void GlpkBase::_eraseRowId(int i) {
78 80
    rows.eraseIndex(i);
79 81
    rows.shiftIndices(i);
80 82
  }
81 83

	
82 84
  void GlpkBase::_getColName(int c, std::string& name) const {
83 85
    const char *str = glp_get_col_name(lp, c);
84 86
    if (str) name = str;
85 87
    else name.clear();
86 88
  }
87 89

	
88 90
  void GlpkBase::_setColName(int c, const std::string & name) {
89 91
    glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
... ...
@@ -481,188 +483,180 @@
481 483
        ++b;
482 484
      }
483 485
    }
484 486
  }
485 487

	
486 488
  void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
487 489
    //i = 0 means the constant term (shift)
488 490
    glp_set_obj_coef(lp, i, obj_coef);
489 491
  }
490 492

	
491 493
  GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
492 494
    //i = 0 means the constant term (shift)
493 495
    return glp_get_obj_coef(lp, i);
494 496
  }
495 497

	
496 498
  void GlpkBase::_setSense(GlpkBase::Sense sense) {
497 499
    switch (sense) {
498 500
    case MIN:
499 501
      glp_set_obj_dir(lp, GLP_MIN);
500 502
      break;
501 503
    case MAX:
502 504
      glp_set_obj_dir(lp, GLP_MAX);
503 505
      break;
504 506
    }
505 507
  }
506 508

	
507 509
  GlpkBase::Sense GlpkBase::_getSense() const {
508 510
    switch(glp_get_obj_dir(lp)) {
509 511
    case GLP_MIN:
510 512
      return MIN;
511 513
    case GLP_MAX:
512 514
      return MAX;
513 515
    default:
514 516
      LEMON_ASSERT(false, "Wrong sense");
515 517
      return GlpkBase::Sense();
516 518
    }
517 519
  }
518 520

	
519 521
  void GlpkBase::_clear() {
520 522
    glp_erase_prob(lp);
521 523
    rows.clear();
522 524
    cols.clear();
523 525
  }
524 526

	
525 527
  void GlpkBase::freeEnv() {
526 528
    glp_free_env();
527 529
  }
528 530

	
531
  void GlpkBase::_messageLevel(MessageLevel level) {
532
    switch (level) {
533
    case MESSAGE_NOTHING:
534
      _message_level = GLP_MSG_OFF;
535
      break;
536
    case MESSAGE_ERROR:
537
      _message_level = GLP_MSG_ERR;
538
      break;
539
    case MESSAGE_WARNING:
540
      _message_level = GLP_MSG_ERR;
541
      break;
542
    case MESSAGE_NORMAL:
543
      _message_level = GLP_MSG_ON;
544
      break;
545
    case MESSAGE_VERBOSE:
546
      _message_level = GLP_MSG_ALL;
547
      break;
548
    }
549
  }
550

	
529 551
  GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
530 552

	
531 553
  // GlpkLp members
532 554

	
533 555
  GlpkLp::GlpkLp()
534 556
    : LpBase(), LpSolver(), GlpkBase() {
535
    messageLevel(MESSAGE_NO_OUTPUT);
536 557
    presolver(false);
537 558
  }
538 559

	
539 560
  GlpkLp::GlpkLp(const GlpkLp& other)
540 561
    : LpBase(other), LpSolver(other), GlpkBase(other) {
541
    messageLevel(MESSAGE_NO_OUTPUT);
542 562
    presolver(false);
543 563
  }
544 564

	
545 565
  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
546 566
  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
547 567

	
548 568
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
549 569

	
550 570
  void GlpkLp::_clear_temporals() {
551 571
    _primal_ray.clear();
552 572
    _dual_ray.clear();
553 573
  }
554 574

	
555 575
  GlpkLp::SolveExitStatus GlpkLp::_solve() {
556 576
    return solvePrimal();
557 577
  }
558 578

	
559 579
  GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
560 580
    _clear_temporals();
561 581

	
562 582
    glp_smcp smcp;
563 583
    glp_init_smcp(&smcp);
564 584

	
565
    switch (_message_level) {
566
    case MESSAGE_NO_OUTPUT:
567
      smcp.msg_lev = GLP_MSG_OFF;
568
      break;
569
    case MESSAGE_ERROR_MESSAGE:
570
      smcp.msg_lev = GLP_MSG_ERR;
571
      break;
572
    case MESSAGE_NORMAL_OUTPUT:
573
      smcp.msg_lev = GLP_MSG_ON;
574
      break;
575
    case MESSAGE_FULL_OUTPUT:
576
      smcp.msg_lev = GLP_MSG_ALL;
577
      break;
578
    }
585
    smcp.msg_lev = _message_level;
579 586
    smcp.presolve = _presolve;
580 587

	
581 588
    // If the basis is not valid we get an error return value.
582 589
    // In this case we can try to create a new basis.
583 590
    switch (glp_simplex(lp, &smcp)) {
584 591
    case 0:
585 592
      break;
586 593
    case GLP_EBADB:
587 594
    case GLP_ESING:
588 595
    case GLP_ECOND:
589 596
      glp_term_out(false);
590 597
      glp_adv_basis(lp, 0);
591 598
      glp_term_out(true);
592 599
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
593 600
      break;
594 601
    default:
595 602
      return UNSOLVED;
596 603
    }
597 604

	
598 605
    return SOLVED;
599 606
  }
600 607

	
601 608
  GlpkLp::SolveExitStatus GlpkLp::solveDual() {
602 609
    _clear_temporals();
603 610

	
604 611
    glp_smcp smcp;
605 612
    glp_init_smcp(&smcp);
606 613

	
607
    switch (_message_level) {
608
    case MESSAGE_NO_OUTPUT:
609
      smcp.msg_lev = GLP_MSG_OFF;
610
      break;
611
    case MESSAGE_ERROR_MESSAGE:
612
      smcp.msg_lev = GLP_MSG_ERR;
613
      break;
614
    case MESSAGE_NORMAL_OUTPUT:
615
      smcp.msg_lev = GLP_MSG_ON;
616
      break;
617
    case MESSAGE_FULL_OUTPUT:
618
      smcp.msg_lev = GLP_MSG_ALL;
619
      break;
620
    }
614
    smcp.msg_lev = _message_level;
621 615
    smcp.meth = GLP_DUAL;
622 616
    smcp.presolve = _presolve;
623 617

	
624 618
    // If the basis is not valid we get an error return value.
625 619
    // In this case we can try to create a new basis.
626 620
    switch (glp_simplex(lp, &smcp)) {
627 621
    case 0:
628 622
      break;
629 623
    case GLP_EBADB:
630 624
    case GLP_ESING:
631 625
    case GLP_ECOND:
632 626
      glp_term_out(false);
633 627
      glp_adv_basis(lp, 0);
634 628
      glp_term_out(true);
635 629
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
636 630
      break;
637 631
    default:
638 632
      return UNSOLVED;
639 633
    }
640 634
    return SOLVED;
641 635
  }
642 636

	
643 637
  GlpkLp::Value GlpkLp::_getPrimal(int i) const {
644 638
    return glp_get_col_prim(lp, i);
645 639
  }
646 640

	
647 641
  GlpkLp::Value GlpkLp::_getDual(int i) const {
648 642
    return glp_get_row_dual(lp, i);
649 643
  }
650 644

	
651 645
  GlpkLp::Value GlpkLp::_getPrimalValue() const {
652 646
    return glp_get_obj_val(lp);
653 647
  }
654 648

	
655 649
  GlpkLp::VarStatus GlpkLp::_getColStatus(int i) const {
656 650
    switch (glp_get_col_stat(lp, i)) {
657 651
    case GLP_BS:
658 652
      return BASIC;
659 653
    case GLP_UP:
660 654
      return UPPER;
661 655
    case GLP_LO:
662 656
      return LOWER;
663 657
    case GLP_NF:
664 658
      return FREE;
665 659
    case GLP_NS:
666 660
      return FIXED;
667 661
    default:
668 662
      LEMON_ASSERT(false, "Wrong column status");
... ...
@@ -813,197 +807,161 @@
813 807
  }
814 808

	
815 809
  GlpkLp::ProblemType GlpkLp::_getPrimalType() const {
816 810
    if (glp_get_status(lp) == GLP_OPT)
817 811
      return OPTIMAL;
818 812
    switch (glp_get_prim_stat(lp)) {
819 813
    case GLP_UNDEF:
820 814
      return UNDEFINED;
821 815
    case GLP_FEAS:
822 816
    case GLP_INFEAS:
823 817
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
824 818
        return UNBOUNDED;
825 819
      } else {
826 820
        return UNDEFINED;
827 821
      }
828 822
    case GLP_NOFEAS:
829 823
      return INFEASIBLE;
830 824
    default:
831 825
      LEMON_ASSERT(false, "Wrong primal type");
832 826
      return  GlpkLp::ProblemType();
833 827
    }
834 828
  }
835 829

	
836 830
  GlpkLp::ProblemType GlpkLp::_getDualType() const {
837 831
    if (glp_get_status(lp) == GLP_OPT)
838 832
      return OPTIMAL;
839 833
    switch (glp_get_dual_stat(lp)) {
840 834
    case GLP_UNDEF:
841 835
      return UNDEFINED;
842 836
    case GLP_FEAS:
843 837
    case GLP_INFEAS:
844 838
      if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
845 839
        return UNBOUNDED;
846 840
      } else {
847 841
        return UNDEFINED;
848 842
      }
849 843
    case GLP_NOFEAS:
850 844
      return INFEASIBLE;
851 845
    default:
852 846
      LEMON_ASSERT(false, "Wrong primal type");
853 847
      return  GlpkLp::ProblemType();
854 848
    }
855 849
  }
856 850

	
857 851
  void GlpkLp::presolver(bool presolve) {
858 852
    _presolve = presolve;
859 853
  }
860 854

	
861
  void GlpkLp::messageLevel(MessageLevel m) {
862
    _message_level = m;
863
  }
864

	
865 855
  // GlpkMip members
866 856

	
867 857
  GlpkMip::GlpkMip()
868 858
    : LpBase(), MipSolver(), GlpkBase() {
869
    messageLevel(MESSAGE_NO_OUTPUT);
870 859
  }
871 860

	
872 861
  GlpkMip::GlpkMip(const GlpkMip& other)
873 862
    : LpBase(), MipSolver(), GlpkBase(other) {
874
    messageLevel(MESSAGE_NO_OUTPUT);
875 863
  }
876 864

	
877 865
  void GlpkMip::_setColType(int i, GlpkMip::ColTypes col_type) {
878 866
    switch (col_type) {
879 867
    case INTEGER:
880 868
      glp_set_col_kind(lp, i, GLP_IV);
881 869
      break;
882 870
    case REAL:
883 871
      glp_set_col_kind(lp, i, GLP_CV);
884 872
      break;
885 873
    }
886 874
  }
887 875

	
888 876
  GlpkMip::ColTypes GlpkMip::_getColType(int i) const {
889 877
    switch (glp_get_col_kind(lp, i)) {
890 878
    case GLP_IV:
891 879
    case GLP_BV:
892 880
      return INTEGER;
893 881
    default:
894 882
      return REAL;
895 883
    }
896 884

	
897 885
  }
898 886

	
899 887
  GlpkMip::SolveExitStatus GlpkMip::_solve() {
900 888
    glp_smcp smcp;
901 889
    glp_init_smcp(&smcp);
902 890

	
903
    switch (_message_level) {
904
    case MESSAGE_NO_OUTPUT:
905
      smcp.msg_lev = GLP_MSG_OFF;
906
      break;
907
    case MESSAGE_ERROR_MESSAGE:
908
      smcp.msg_lev = GLP_MSG_ERR;
909
      break;
910
    case MESSAGE_NORMAL_OUTPUT:
911
      smcp.msg_lev = GLP_MSG_ON;
912
      break;
913
    case MESSAGE_FULL_OUTPUT:
914
      smcp.msg_lev = GLP_MSG_ALL;
915
      break;
916
    }
891
    smcp.msg_lev = _message_level;
917 892
    smcp.meth = GLP_DUAL;
918 893

	
919 894
    // If the basis is not valid we get an error return value.
920 895
    // In this case we can try to create a new basis.
921 896
    switch (glp_simplex(lp, &smcp)) {
922 897
    case 0:
923 898
      break;
924 899
    case GLP_EBADB:
925 900
    case GLP_ESING:
926 901
    case GLP_ECOND:
927 902
      glp_term_out(false);
928 903
      glp_adv_basis(lp, 0);
929 904
      glp_term_out(true);
930 905
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
931 906
      break;
932 907
    default:
933 908
      return UNSOLVED;
934 909
    }
935 910

	
936 911
    if (glp_get_status(lp) != GLP_OPT) return SOLVED;
937 912

	
938 913
    glp_iocp iocp;
939 914
    glp_init_iocp(&iocp);
940 915

	
941
    switch (_message_level) {
942
    case MESSAGE_NO_OUTPUT:
943
      iocp.msg_lev = GLP_MSG_OFF;
944
      break;
945
    case MESSAGE_ERROR_MESSAGE:
946
      iocp.msg_lev = GLP_MSG_ERR;
947
      break;
948
    case MESSAGE_NORMAL_OUTPUT:
949
      iocp.msg_lev = GLP_MSG_ON;
950
      break;
951
    case MESSAGE_FULL_OUTPUT:
952
      iocp.msg_lev = GLP_MSG_ALL;
953
      break;
954
    }
916
    iocp.msg_lev = _message_level;
955 917

	
956 918
    if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
957 919
    return SOLVED;
958 920
  }
959 921

	
960 922

	
961 923
  GlpkMip::ProblemType GlpkMip::_getType() const {
962 924
    switch (glp_get_status(lp)) {
963 925
    case GLP_OPT:
964 926
      switch (glp_mip_status(lp)) {
965 927
      case GLP_UNDEF:
966 928
        return UNDEFINED;
967 929
      case GLP_NOFEAS:
968 930
        return INFEASIBLE;
969 931
      case GLP_FEAS:
970 932
        return FEASIBLE;
971 933
      case GLP_OPT:
972 934
        return OPTIMAL;
973 935
      default:
974 936
        LEMON_ASSERT(false, "Wrong problem type.");
975 937
        return GlpkMip::ProblemType();
976 938
      }
977 939
    case GLP_NOFEAS:
978 940
      return INFEASIBLE;
979 941
    case GLP_INFEAS:
980 942
    case GLP_FEAS:
981 943
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
982 944
        return UNBOUNDED;
983 945
      } else {
984 946
        return UNDEFINED;
985 947
      }
986 948
    default:
987 949
      LEMON_ASSERT(false, "Wrong problem type.");
988 950
      return GlpkMip::ProblemType();
989 951
    }
990 952
  }
991 953

	
992 954
  GlpkMip::Value GlpkMip::_getSol(int i) const {
993 955
    return glp_mip_col_val(lp, i);
994 956
  }
995 957

	
996 958
  GlpkMip::Value GlpkMip::_getSolValue() const {
997 959
    return glp_mip_obj_val(lp);
998 960
  }
999 961

	
1000 962
  GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; }
1001 963
  GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); }
1002 964

	
1003 965
  const char* GlpkMip::_solverName() const { return "GlpkMip"; }
1004 966

	
1005
  void GlpkMip::messageLevel(MessageLevel m) {
1006
    _message_level = m;
1007
  }
1008

	
1009 967
} //END OF NAMESPACE LEMON
Ignore white space 6 line context
... ...
@@ -55,223 +55,181 @@
55 55
    virtual int _addRow();
56 56

	
57 57
    virtual void _eraseCol(int i);
58 58
    virtual void _eraseRow(int i);
59 59

	
60 60
    virtual void _eraseColId(int i);
61 61
    virtual void _eraseRowId(int i);
62 62

	
63 63
    virtual void _getColName(int col, std::string& name) const;
64 64
    virtual void _setColName(int col, const std::string& name);
65 65
    virtual int _colByName(const std::string& name) const;
66 66

	
67 67
    virtual void _getRowName(int row, std::string& name) const;
68 68
    virtual void _setRowName(int row, const std::string& name);
69 69
    virtual int _rowByName(const std::string& name) const;
70 70

	
71 71
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
72 72
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
73 73

	
74 74
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
75 75
    virtual void _getColCoeffs(int i, InsertIterator b) const;
76 76

	
77 77
    virtual void _setCoeff(int row, int col, Value value);
78 78
    virtual Value _getCoeff(int row, int col) const;
79 79

	
80 80
    virtual void _setColLowerBound(int i, Value value);
81 81
    virtual Value _getColLowerBound(int i) const;
82 82

	
83 83
    virtual void _setColUpperBound(int i, Value value);
84 84
    virtual Value _getColUpperBound(int i) const;
85 85

	
86 86
    virtual void _setRowLowerBound(int i, Value value);
87 87
    virtual Value _getRowLowerBound(int i) const;
88 88

	
89 89
    virtual void _setRowUpperBound(int i, Value value);
90 90
    virtual Value _getRowUpperBound(int i) const;
91 91

	
92 92
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
93 93
    virtual void _getObjCoeffs(InsertIterator b) const;
94 94

	
95 95
    virtual void _setObjCoeff(int i, Value obj_coef);
96 96
    virtual Value _getObjCoeff(int i) const;
97 97

	
98 98
    virtual void _setSense(Sense);
99 99
    virtual Sense _getSense() const;
100 100

	
101 101
    virtual void _clear();
102 102

	
103
    virtual void _messageLevel(MessageLevel level);
104

	
103 105
  private:
104 106

	
105 107
    static void freeEnv();
106 108

	
107 109
    struct FreeEnvHelper {
108 110
      ~FreeEnvHelper() {
109 111
        freeEnv();
110 112
      }
111 113
    };
112 114
    
113 115
    static FreeEnvHelper freeEnvHelper;
116

	
117
  protected:
118
    
119
    int _message_level;
114 120
    
115 121
  public:
116 122

	
117 123
    ///Pointer to the underlying GLPK data structure.
118 124
    LPX *lpx() {return lp;}
119 125
    ///Const pointer to the underlying GLPK data structure.
120 126
    const LPX *lpx() const {return lp;}
121 127

	
122 128
    ///Returns the constraint identifier understood by GLPK.
123 129
    int lpxRow(Row r) const { return rows(id(r)); }
124 130

	
125 131
    ///Returns the variable identifier understood by GLPK.
126 132
    int lpxCol(Col c) const { return cols(id(c)); }
127 133

	
128 134
  };
129 135

	
130 136
  /// \brief Interface for the GLPK LP solver
131 137
  ///
132 138
  /// This class implements an interface for the GLPK LP solver.
133 139
  ///\ingroup lp_group
134 140
  class GlpkLp : public LpSolver, public GlpkBase {
135 141
  public:
136 142

	
137 143
    ///\e
138 144
    GlpkLp();
139 145
    ///\e
140 146
    GlpkLp(const GlpkLp&);
141 147

	
142 148
    ///\e
143 149
    virtual GlpkLp* cloneSolver() const;
144 150
    ///\e
145 151
    virtual GlpkLp* newSolver() const;
146 152

	
147 153
  private:
148 154

	
149 155
    mutable std::vector<double> _primal_ray;
150 156
    mutable std::vector<double> _dual_ray;
151 157

	
152 158
    void _clear_temporals();
153 159

	
154 160
  protected:
155 161

	
156 162
    virtual const char* _solverName() const;
157 163

	
158 164
    virtual SolveExitStatus _solve();
159 165
    virtual Value _getPrimal(int i) const;
160 166
    virtual Value _getDual(int i) const;
161 167

	
162 168
    virtual Value _getPrimalValue() const;
163 169

	
164 170
    virtual VarStatus _getColStatus(int i) const;
165 171
    virtual VarStatus _getRowStatus(int i) const;
166 172

	
167 173
    virtual Value _getPrimalRay(int i) const;
168 174
    virtual Value _getDualRay(int i) const;
169 175

	
170 176
    virtual ProblemType _getPrimalType() const;
171 177
    virtual ProblemType _getDualType() const;
172 178

	
173 179
  public:
174 180

	
175 181
    ///Solve with primal simplex
176 182
    SolveExitStatus solvePrimal();
177 183

	
178 184
    ///Solve with dual simplex
179 185
    SolveExitStatus solveDual();
180 186

	
181 187
  private:
182 188

	
183 189
    bool _presolve;
184 190

	
185 191
  public:
186 192

	
187 193
    ///Turns on or off the presolver
188 194

	
189 195
    ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
190 196
    ///
191 197
    ///The presolver is off by default.
192 198
    void presolver(bool presolve);
193 199

	
194
    ///Enum for \c messageLevel() parameter
195
    enum MessageLevel {
196
      /// no output (default value)
197
      MESSAGE_NO_OUTPUT = 0,
198
      /// error messages only
199
      MESSAGE_ERROR_MESSAGE = 1,
200
      /// normal output
201
      MESSAGE_NORMAL_OUTPUT = 2,
202
      /// full output (includes informational messages)
203
      MESSAGE_FULL_OUTPUT = 3
204
    };
205

	
206
  private:
207

	
208
    MessageLevel _message_level;
209

	
210
  public:
211

	
212
    ///Set the verbosity of the messages
213

	
214
    ///Set the verbosity of the messages
215
    ///
216
    ///\param m is the level of the messages output by the solver routines.
217
    void messageLevel(MessageLevel m);
218 200
  };
219 201

	
220 202
  /// \brief Interface for the GLPK MIP solver
221 203
  ///
222 204
  /// This class implements an interface for the GLPK MIP solver.
223 205
  ///\ingroup lp_group
224 206
  class GlpkMip : public MipSolver, public GlpkBase {
225 207
  public:
226 208

	
227 209
    ///\e
228 210
    GlpkMip();
229 211
    ///\e
230 212
    GlpkMip(const GlpkMip&);
231 213

	
232 214
    virtual GlpkMip* cloneSolver() const;
233 215
    virtual GlpkMip* newSolver() const;
234 216

	
235 217
  protected:
236 218

	
237 219
    virtual const char* _solverName() const;
238 220

	
239 221
    virtual ColTypes _getColType(int col) const;
240 222
    virtual void _setColType(int col, ColTypes col_type);
241 223

	
242 224
    virtual SolveExitStatus _solve();
243 225
    virtual ProblemType _getType() const;
244 226
    virtual Value _getSol(int i) const;
245 227
    virtual Value _getSolValue() const;
246 228

	
247
    ///Enum for \c messageLevel() parameter
248
    enum MessageLevel {
249
      /// no output (default value)
250
      MESSAGE_NO_OUTPUT = 0,
251
      /// error messages only
252
      MESSAGE_ERROR_MESSAGE = 1,
253
      /// normal output
254
      MESSAGE_NORMAL_OUTPUT = 2,
255
      /// full output (includes informational messages)
256
      MESSAGE_FULL_OUTPUT = 3
257
    };
258

	
259
  private:
260

	
261
    MessageLevel _message_level;
262

	
263
  public:
264

	
265
    ///Set the verbosity of the messages
266

	
267
    ///Set the verbosity of the messages
268
    ///
269
    ///\param m is the level of the messages output by the solver routines.
270
    void messageLevel(MessageLevel m);
271 229
  };
272 230

	
273 231

	
274 232
} //END OF NAMESPACE LEMON
275 233

	
276 234
#endif //LEMON_GLPK_H
277 235

	
Ignore white space 6 line context
... ...
@@ -24,96 +24,111 @@
24 24
#include<map>
25 25
#include<limits>
26 26
#include<lemon/math.h>
27 27

	
28 28
#include<lemon/error.h>
29 29
#include<lemon/assert.h>
30 30

	
31 31
#include<lemon/core.h>
32 32
#include<lemon/bits/solver_bits.h>
33 33

	
34 34
///\file
35 35
///\brief The interface of the LP solver interface.
36 36
///\ingroup lp_group
37 37
namespace lemon {
38 38

	
39 39
  ///Common base class for LP and MIP solvers
40 40

	
41 41
  ///Usually this class is not used directly, please use one of the concrete
42 42
  ///implementations of the solver interface.
43 43
  ///\ingroup lp_group
44 44
  class LpBase {
45 45

	
46 46
  protected:
47 47

	
48 48
    _solver_bits::VarIndex rows;
49 49
    _solver_bits::VarIndex cols;
50 50

	
51 51
  public:
52 52

	
53 53
    ///Possible outcomes of an LP solving procedure
54 54
    enum SolveExitStatus {
55 55
      ///This means that the problem has been successfully solved: either
56 56
      ///an optimal solution has been found or infeasibility/unboundedness
57 57
      ///has been proved.
58 58
      SOLVED = 0,
59 59
      ///Any other case (including the case when some user specified
60 60
      ///limit has been exceeded)
61 61
      UNSOLVED = 1
62 62
    };
63 63

	
64 64
    ///Direction of the optimization
65 65
    enum Sense {
66 66
      /// Minimization
67 67
      MIN,
68 68
      /// Maximization
69 69
      MAX
70 70
    };
71 71

	
72
    ///Enum for \c messageLevel() parameter
73
    enum MessageLevel {
74
      /// no output (default value)
75
      MESSAGE_NOTHING,
76
      /// error messages only
77
      MESSAGE_ERROR,
78
      /// warnings
79
      MESSAGE_WARNING,
80
      /// normal output
81
      MESSAGE_NORMAL,
82
      /// verbose output
83
      MESSAGE_VERBOSE
84
    };
85
    
86

	
72 87
    ///The floating point type used by the solver
73 88
    typedef double Value;
74 89
    ///The infinity constant
75 90
    static const Value INF;
76 91
    ///The not a number constant
77 92
    static const Value NaN;
78 93

	
79 94
    friend class Col;
80 95
    friend class ColIt;
81 96
    friend class Row;
82 97
    friend class RowIt;
83 98

	
84 99
    ///Refer to a column of the LP.
85 100

	
86 101
    ///This type is used to refer to a column of the LP.
87 102
    ///
88 103
    ///Its value remains valid and correct even after the addition or erase of
89 104
    ///other columns.
90 105
    ///
91 106
    ///\note This class is similar to other Item types in LEMON, like
92 107
    ///Node and Arc types in digraph.
93 108
    class Col {
94 109
      friend class LpBase;
95 110
    protected:
96 111
      int _id;
97 112
      explicit Col(int id) : _id(id) {}
98 113
    public:
99 114
      typedef Value ExprValue;
100 115
      typedef True LpCol;
101 116
      /// Default constructor
102 117
      
103 118
      /// \warning The default constructor sets the Col to an
104 119
      /// undefined value.
105 120
      Col() {}
106 121
      /// Invalid constructor \& conversion.
107 122
      
108 123
      /// This constructor initializes the Col to be invalid.
109 124
      /// \sa Invalid for more details.      
110 125
      Col(const Invalid&) : _id(-1) {}
111 126
      /// Equality operator
112 127

	
113 128
      /// Two \ref Col "Col"s are equal if and only if they point to
114 129
      /// the same LP column or both are invalid.
115 130
      bool operator==(Col c) const  {return _id == c._id;}
116 131
      /// Inequality operator
117 132

	
118 133
      /// \sa operator==(Col c)
119 134
      ///
... ...
@@ -928,96 +943,98 @@
928 943
    virtual int _addCol() = 0;
929 944
    virtual int _addRow() = 0;
930 945

	
931 946
    virtual void _eraseCol(int col) = 0;
932 947
    virtual void _eraseRow(int row) = 0;
933 948

	
934 949
    virtual void _getColName(int col, std::string& name) const = 0;
935 950
    virtual void _setColName(int col, const std::string& name) = 0;
936 951
    virtual int _colByName(const std::string& name) const = 0;
937 952

	
938 953
    virtual void _getRowName(int row, std::string& name) const = 0;
939 954
    virtual void _setRowName(int row, const std::string& name) = 0;
940 955
    virtual int _rowByName(const std::string& name) const = 0;
941 956

	
942 957
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
943 958
    virtual void _getRowCoeffs(int i, InsertIterator b) const = 0;
944 959

	
945 960
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
946 961
    virtual void _getColCoeffs(int i, InsertIterator b) const = 0;
947 962

	
948 963
    virtual void _setCoeff(int row, int col, Value value) = 0;
949 964
    virtual Value _getCoeff(int row, int col) const = 0;
950 965

	
951 966
    virtual void _setColLowerBound(int i, Value value) = 0;
952 967
    virtual Value _getColLowerBound(int i) const = 0;
953 968

	
954 969
    virtual void _setColUpperBound(int i, Value value) = 0;
955 970
    virtual Value _getColUpperBound(int i) const = 0;
956 971

	
957 972
    virtual void _setRowLowerBound(int i, Value value) = 0;
958 973
    virtual Value _getRowLowerBound(int i) const = 0;
959 974

	
960 975
    virtual void _setRowUpperBound(int i, Value value) = 0;
961 976
    virtual Value _getRowUpperBound(int i) const = 0;
962 977

	
963 978
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e) = 0;
964 979
    virtual void _getObjCoeffs(InsertIterator b) const = 0;
965 980

	
966 981
    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
967 982
    virtual Value _getObjCoeff(int i) const = 0;
968 983

	
969 984
    virtual void _setSense(Sense) = 0;
970 985
    virtual Sense _getSense() const = 0;
971 986

	
972 987
    virtual void _clear() = 0;
973 988

	
974 989
    virtual const char* _solverName() const = 0;
975 990

	
991
    virtual void _messageLevel(MessageLevel level) = 0;
992

	
976 993
    //Own protected stuff
977 994

	
978 995
    //Constant component of the objective function
979 996
    Value obj_const_comp;
980 997

	
981 998
    LpBase() : rows(), cols(), obj_const_comp(0) {}
982 999

	
983 1000
  public:
984 1001

	
985 1002
    /// Virtual destructor
986 1003
    virtual ~LpBase() {}
987 1004

	
988 1005
    ///Gives back the name of the solver.
989 1006
    const char* solverName() const {return _solverName();}
990 1007

	
991 1008
    ///\name Build up and modify the LP
992 1009

	
993 1010
    ///@{
994 1011

	
995 1012
    ///Add a new empty column (i.e a new variable) to the LP
996 1013
    Col addCol() { Col c; c._id = _addColId(_addCol()); return c;}
997 1014

	
998 1015
    ///\brief Adds several new columns (i.e variables) at once
999 1016
    ///
1000 1017
    ///This magic function takes a container as its argument and fills
1001 1018
    ///its elements with new columns (i.e. variables)
1002 1019
    ///\param t can be
1003 1020
    ///- a standard STL compatible iterable container with
1004 1021
    ///\ref Col as its \c values_type like
1005 1022
    ///\code
1006 1023
    ///std::vector<LpBase::Col>
1007 1024
    ///std::list<LpBase::Col>
1008 1025
    ///\endcode
1009 1026
    ///- a standard STL compatible iterable container with
1010 1027
    ///\ref Col as its \c mapped_type like
1011 1028
    ///\code
1012 1029
    ///std::map<AnyType,LpBase::Col>
1013 1030
    ///\endcode
1014 1031
    ///- an iterable lemon \ref concepts::WriteMap "write map" like
1015 1032
    ///\code
1016 1033
    ///ListGraph::NodeMap<LpBase::Col>
1017 1034
    ///ListGraph::ArcMap<LpBase::Col>
1018 1035
    ///\endcode
1019 1036
    ///\return The number of the created column.
1020 1037
#ifdef DOXYGEN
1021 1038
    template<class T>
1022 1039
    int addColSet(T &t) { return 0;}
1023 1040
#else
... ...
@@ -1482,96 +1499,99 @@
1482 1499
    ///\return The upper bound for row \c r
1483 1500
    Value rowUpperBound(Row r) const {
1484 1501
      return _getRowUpperBound(rows(id(r)));
1485 1502
    }
1486 1503

	
1487 1504
    ///Set an element of the objective function
1488 1505
    void objCoeff(Col c, Value v) {_setObjCoeff(cols(id(c)),v); };
1489 1506

	
1490 1507
    ///Get an element of the objective function
1491 1508
    Value objCoeff(Col c) const { return _getObjCoeff(cols(id(c))); };
1492 1509

	
1493 1510
    ///Set the objective function
1494 1511

	
1495 1512
    ///\param e is a linear expression of type \ref Expr.
1496 1513
    ///
1497 1514
    void obj(const Expr& e) {
1498 1515
      _setObjCoeffs(ExprIterator(e.comps.begin(), cols),
1499 1516
                    ExprIterator(e.comps.end(), cols));
1500 1517
      obj_const_comp = *e;
1501 1518
    }
1502 1519

	
1503 1520
    ///Get the objective function
1504 1521

	
1505 1522
    ///\return the objective function as a linear expression of type
1506 1523
    ///Expr.
1507 1524
    Expr obj() const {
1508 1525
      Expr e;
1509 1526
      _getObjCoeffs(InsertIterator(e.comps, cols));
1510 1527
      *e = obj_const_comp;
1511 1528
      return e;
1512 1529
    }
1513 1530

	
1514 1531

	
1515 1532
    ///Set the direction of optimization
1516 1533
    void sense(Sense sense) { _setSense(sense); }
1517 1534

	
1518 1535
    ///Query the direction of the optimization
1519 1536
    Sense sense() const {return _getSense(); }
1520 1537

	
1521 1538
    ///Set the sense to maximization
1522 1539
    void max() { _setSense(MAX); }
1523 1540

	
1524 1541
    ///Set the sense to maximization
1525 1542
    void min() { _setSense(MIN); }
1526 1543

	
1527 1544
    ///Clears the problem
1528 1545
    void clear() { _clear(); }
1529 1546

	
1547
    /// Sets the message level of the solver
1548
    void messageLevel(MessageLevel level) { _messageLevel(level); }
1549

	
1530 1550
    ///@}
1531 1551

	
1532 1552
  };
1533 1553

	
1534 1554
  /// Addition
1535 1555

	
1536 1556
  ///\relates LpBase::Expr
1537 1557
  ///
1538 1558
  inline LpBase::Expr operator+(const LpBase::Expr &a, const LpBase::Expr &b) {
1539 1559
    LpBase::Expr tmp(a);
1540 1560
    tmp+=b;
1541 1561
    return tmp;
1542 1562
  }
1543 1563
  ///Substraction
1544 1564

	
1545 1565
  ///\relates LpBase::Expr
1546 1566
  ///
1547 1567
  inline LpBase::Expr operator-(const LpBase::Expr &a, const LpBase::Expr &b) {
1548 1568
    LpBase::Expr tmp(a);
1549 1569
    tmp-=b;
1550 1570
    return tmp;
1551 1571
  }
1552 1572
  ///Multiply with constant
1553 1573

	
1554 1574
  ///\relates LpBase::Expr
1555 1575
  ///
1556 1576
  inline LpBase::Expr operator*(const LpBase::Expr &a, const LpBase::Value &b) {
1557 1577
    LpBase::Expr tmp(a);
1558 1578
    tmp*=b;
1559 1579
    return tmp;
1560 1580
  }
1561 1581

	
1562 1582
  ///Multiply with constant
1563 1583

	
1564 1584
  ///\relates LpBase::Expr
1565 1585
  ///
1566 1586
  inline LpBase::Expr operator*(const LpBase::Value &a, const LpBase::Expr &b) {
1567 1587
    LpBase::Expr tmp(b);
1568 1588
    tmp*=a;
1569 1589
    return tmp;
1570 1590
  }
1571 1591
  ///Divide with constant
1572 1592

	
1573 1593
  ///\relates LpBase::Expr
1574 1594
  ///
1575 1595
  inline LpBase::Expr operator/(const LpBase::Expr &a, const LpBase::Value &b) {
1576 1596
    LpBase::Expr tmp(a);
1577 1597
    tmp/=b;
Ignore white space 6 line context
... ...
@@ -39,96 +39,98 @@
39 39
  void SkeletonSolverBase::_setColName(int, const std::string &) {}
40 40
  int SkeletonSolverBase::_colByName(const std::string&) const { return -1; }
41 41

	
42 42
  void SkeletonSolverBase::_getRowName(int, std::string &) const {}
43 43
  void SkeletonSolverBase::_setRowName(int, const std::string &) {}
44 44
  int SkeletonSolverBase::_rowByName(const std::string&) const { return -1; }
45 45

	
46 46
  void SkeletonSolverBase::_setRowCoeffs(int, ExprIterator, ExprIterator) {}
47 47
  void SkeletonSolverBase::_getRowCoeffs(int, InsertIterator) const {}
48 48

	
49 49
  void SkeletonSolverBase::_setColCoeffs(int, ExprIterator, ExprIterator) {}
50 50
  void SkeletonSolverBase::_getColCoeffs(int, InsertIterator) const {}
51 51

	
52 52
  void SkeletonSolverBase::_setCoeff(int, int, Value) {}
53 53
  SkeletonSolverBase::Value SkeletonSolverBase::_getCoeff(int, int) const
54 54
  { return 0; }
55 55

	
56 56
  void SkeletonSolverBase::_setColLowerBound(int, Value) {}
57 57
  SkeletonSolverBase::Value SkeletonSolverBase::_getColLowerBound(int) const
58 58
  {  return 0; }
59 59

	
60 60
  void SkeletonSolverBase::_setColUpperBound(int, Value) {}
61 61
  SkeletonSolverBase::Value SkeletonSolverBase::_getColUpperBound(int) const
62 62
  {  return 0; }
63 63

	
64 64
  void SkeletonSolverBase::_setRowLowerBound(int, Value) {}
65 65
  SkeletonSolverBase::Value SkeletonSolverBase::_getRowLowerBound(int) const
66 66
  {  return 0; }
67 67

	
68 68
  void SkeletonSolverBase::_setRowUpperBound(int, Value) {}
69 69
  SkeletonSolverBase::Value SkeletonSolverBase::_getRowUpperBound(int) const
70 70
  {  return 0; }
71 71

	
72 72
  void SkeletonSolverBase::_setObjCoeffs(ExprIterator, ExprIterator) {}
73 73
  void SkeletonSolverBase::_getObjCoeffs(InsertIterator) const {};
74 74

	
75 75
  void SkeletonSolverBase::_setObjCoeff(int, Value) {}
76 76
  SkeletonSolverBase::Value SkeletonSolverBase::_getObjCoeff(int) const
77 77
  {  return 0; }
78 78

	
79 79
  void SkeletonSolverBase::_setSense(Sense) {}
80 80
  SkeletonSolverBase::Sense SkeletonSolverBase::_getSense() const
81 81
  { return MIN; }
82 82

	
83 83
  void SkeletonSolverBase::_clear() {
84 84
    row_num = col_num = 0;
85 85
  }
86 86

	
87
  void SkeletonSolverBase::_messageLevel(MessageLevel) {}
88

	
87 89
  LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; }
88 90

	
89 91
  LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; }
90 92
  LpSkeleton::Value LpSkeleton::_getDual(int) const { return 0; }
91 93
  LpSkeleton::Value LpSkeleton::_getPrimalValue() const { return 0; }
92 94

	
93 95
  LpSkeleton::Value LpSkeleton::_getPrimalRay(int) const { return 0; }
94 96
  LpSkeleton::Value LpSkeleton::_getDualRay(int) const { return 0; }
95 97

	
96 98
  LpSkeleton::ProblemType LpSkeleton::_getPrimalType() const
97 99
  { return UNDEFINED; }
98 100

	
99 101
  LpSkeleton::ProblemType LpSkeleton::_getDualType() const
100 102
  { return UNDEFINED; }
101 103

	
102 104
  LpSkeleton::VarStatus LpSkeleton::_getColStatus(int) const
103 105
  { return BASIC; }
104 106

	
105 107
  LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const
106 108
  { return BASIC; }
107 109

	
108 110
  LpSkeleton* LpSkeleton::newSolver() const
109 111
  { return static_cast<LpSkeleton*>(0); }
110 112

	
111 113
  LpSkeleton* LpSkeleton::cloneSolver() const
112 114
  { return static_cast<LpSkeleton*>(0); }
113 115

	
114 116
  const char* LpSkeleton::_solverName() const { return "LpSkeleton"; }
115 117

	
116 118
  MipSkeleton::SolveExitStatus MipSkeleton::_solve()
117 119
  { return SOLVED; }
118 120

	
119 121
  MipSkeleton::Value MipSkeleton::_getSol(int) const { return 0; }
120 122
  MipSkeleton::Value MipSkeleton::_getSolValue() const { return 0; }
121 123

	
122 124
  MipSkeleton::ProblemType MipSkeleton::_getType() const
123 125
  { return UNDEFINED; }
124 126

	
125 127
  MipSkeleton* MipSkeleton::newSolver() const
126 128
  { return static_cast<MipSkeleton*>(0); }
127 129

	
128 130
  MipSkeleton* MipSkeleton::cloneSolver() const
129 131
  { return static_cast<MipSkeleton*>(0); }
130 132

	
131 133
  const char* MipSkeleton::_solverName() const { return "MipSkeleton"; }
132 134

	
133 135
} //namespace lemon
134 136

	
Ignore white space 6 line context
... ...
@@ -95,96 +95,98 @@
95 95
    virtual void _setColUpperBound(int i, Value value);
96 96
    /// \e
97 97

	
98 98
    /// The upper bound of a variable (column) is an
99 99
    /// extended number of type Value, i.e. a finite number of type
100 100
    /// Value or \ref INF.
101 101
    virtual Value _getColUpperBound(int i) const;
102 102

	
103 103
    /// The lower bound of a constraint (row) have to be given by an
104 104
    /// extended number of type Value, i.e. a finite number of type
105 105
    /// Value or -\ref INF.
106 106
    virtual void _setRowLowerBound(int i, Value value);
107 107
    /// \e
108 108

	
109 109
    /// The lower bound of a constraint (row) is an
110 110
    /// extended number of type Value, i.e. a finite number of type
111 111
    /// Value or -\ref INF.
112 112
    virtual Value _getRowLowerBound(int i) const;
113 113

	
114 114
    /// The upper bound of a constraint (row) have to be given by an
115 115
    /// extended number of type Value, i.e. a finite number of type
116 116
    /// Value or \ref INF.
117 117
    virtual void _setRowUpperBound(int i, Value value);
118 118
    /// \e
119 119

	
120 120
    /// The upper bound of a constraint (row) is an
121 121
    /// extended number of type Value, i.e. a finite number of type
122 122
    /// Value or \ref INF.
123 123
    virtual Value _getRowUpperBound(int i) const;
124 124

	
125 125
    /// \e
126 126
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
127 127
    /// \e
128 128
    virtual void _getObjCoeffs(InsertIterator b) const;
129 129

	
130 130
    /// \e
131 131
    virtual void _setObjCoeff(int i, Value obj_coef);
132 132
    /// \e
133 133
    virtual Value _getObjCoeff(int i) const;
134 134

	
135 135
    ///\e
136 136
    virtual void _setSense(Sense);
137 137
    ///\e
138 138
    virtual Sense _getSense() const;
139 139

	
140 140
    ///\e
141 141
    virtual void _clear();
142 142

	
143
    ///\e
144
    virtual void _messageLevel(MessageLevel);
143 145
  };
144 146

	
145 147
  /// \brief Skeleton class for an LP solver interface
146 148
  ///
147 149
  ///This class does nothing, but it can serve as a skeleton when
148 150
  ///implementing an interface to new solvers.
149 151

	
150 152
  ///\ingroup lp_group
151 153
  class LpSkeleton : public LpSolver, public SkeletonSolverBase {
152 154
  public:
153 155
    ///\e
154 156
    LpSkeleton() : LpSolver(), SkeletonSolverBase() {}
155 157
    ///\e
156 158
    virtual LpSkeleton* newSolver() const;
157 159
    ///\e
158 160
    virtual LpSkeleton* cloneSolver() const;
159 161
  protected:
160 162

	
161 163
    ///\e
162 164
    virtual SolveExitStatus _solve();
163 165

	
164 166
    ///\e
165 167
    virtual Value _getPrimal(int i) const;
166 168
    ///\e
167 169
    virtual Value _getDual(int i) const;
168 170

	
169 171
    ///\e
170 172
    virtual Value _getPrimalValue() const;
171 173

	
172 174
    ///\e
173 175
    virtual Value _getPrimalRay(int i) const;
174 176
    ///\e
175 177
    virtual Value _getDualRay(int i) const;
176 178

	
177 179
    ///\e
178 180
    virtual ProblemType _getPrimalType() const;
179 181
    ///\e
180 182
    virtual ProblemType _getDualType() const;
181 183

	
182 184
    ///\e
183 185
    virtual VarStatus _getColStatus(int i) const;
184 186
    ///\e
185 187
    virtual VarStatus _getRowStatus(int i) const;
186 188

	
187 189
    ///\e
188 190
    virtual const char* _solverName() const;
189 191

	
190 192
  };
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <iostream>
20 20
#include <lemon/soplex.h>
21 21

	
22 22
#include <soplex.h>
23
#include <spxout.h>
23 24

	
24 25

	
25 26
///\file
26 27
///\brief Implementation of the LEMON-SOPLEX lp solver interface.
27 28
namespace lemon {
28 29

	
29 30
  SoplexLp::SoplexLp() {
30 31
    soplex = new soplex::SoPlex;
32
    messageLevel(MESSAGE_NOTHING);
31 33
  }
32 34

	
33 35
  SoplexLp::~SoplexLp() {
34 36
    delete soplex;
35 37
  }
36 38

	
37 39
  SoplexLp::SoplexLp(const SoplexLp& lp) {
38 40
    rows = lp.rows;
39 41
    cols = lp.cols;
40 42

	
41 43
    soplex = new soplex::SoPlex;
42 44
    (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
43 45

	
44 46
    _col_names = lp._col_names;
45 47
    _col_names_ref = lp._col_names_ref;
46 48

	
47 49
    _row_names = lp._row_names;
48 50
    _row_names_ref = lp._row_names_ref;
49 51

	
52
    messageLevel(MESSAGE_NOTHING);
50 53
  }
51 54

	
52 55
  void SoplexLp::_clear_temporals() {
53 56
    _primal_values.clear();
54 57
    _dual_values.clear();
55 58
  }
56 59

	
57 60
  SoplexLp* SoplexLp::newSolver() const {
58 61
    SoplexLp* newlp = new SoplexLp();
59 62
    return newlp;
60 63
  }
61 64

	
62 65
  SoplexLp* SoplexLp::cloneSolver() const {
63 66
    SoplexLp* newlp = new SoplexLp(*this);
64 67
    return newlp;
65 68
  }
66 69

	
67 70
  const char* SoplexLp::_solverName() const { return "SoplexLp"; }
68 71

	
69 72
  int SoplexLp::_addCol() {
70 73
    soplex::LPCol c;
71 74
    c.setLower(-soplex::infinity);
72 75
    c.setUpper(soplex::infinity);
73 76
    soplex->addCol(c);
74 77

	
75 78
    _col_names.push_back(std::string());
76 79

	
77 80
    return soplex->nCols() - 1;
78 81
  }
79 82

	
80 83
  int SoplexLp::_addRow() {
81 84
    soplex::LPRow r;
82 85
    r.setLhs(-soplex::infinity);
83 86
    r.setRhs(soplex::infinity);
84 87
    soplex->addRow(r);
85 88

	
86 89
    _row_names.push_back(std::string());
87 90

	
88 91
    return soplex->nRows() - 1;
89 92
  }
90 93

	
91 94

	
92 95
  void SoplexLp::_eraseCol(int i) {
93 96
    soplex->removeCol(i);
94 97
    _col_names_ref.erase(_col_names[i]);
95 98
    _col_names[i] = _col_names.back();
96 99
    _col_names_ref[_col_names.back()] = i;
97 100
    _col_names.pop_back();
... ...
@@ -226,96 +229,98 @@
226 229
    soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
227 230
  }
228 231

	
229 232
  SoplexLp::Value SoplexLp::_getRowLowerBound(int i) const {
230 233
    double res = soplex->lhs(i);
231 234
    return res == -soplex::infinity ? -INF : res;
232 235
  }
233 236

	
234 237
  void SoplexLp::_setRowUpperBound(int i, Value ub) {
235 238
    LEMON_ASSERT(ub != -INF, "Invalid bound");
236 239
    soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity);
237 240
  }
238 241

	
239 242
  SoplexLp::Value SoplexLp::_getRowUpperBound(int i) const {
240 243
    double res = soplex->rhs(i);
241 244
    return res == soplex::infinity ? INF : res;
242 245
  }
243 246

	
244 247
  void SoplexLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
245 248
    for (int j = 0; j < soplex->nCols(); ++j) {
246 249
      soplex->changeObj(j, 0.0);
247 250
    }
248 251
    for (ExprIterator it = b; it != e; ++it) {
249 252
      soplex->changeObj(it->first, it->second);
250 253
    }
251 254
  }
252 255

	
253 256
  void SoplexLp::_getObjCoeffs(InsertIterator b) const {
254 257
    for (int j = 0; j < soplex->nCols(); ++j) {
255 258
      Value coef = soplex->obj(j);
256 259
      if (coef != 0.0) {
257 260
        *b = std::make_pair(j, coef);
258 261
        ++b;
259 262
      }
260 263
    }
261 264
  }
262 265

	
263 266
  void SoplexLp::_setObjCoeff(int i, Value obj_coef) {
264 267
    soplex->changeObj(i, obj_coef);
265 268
  }
266 269

	
267 270
  SoplexLp::Value SoplexLp::_getObjCoeff(int i) const {
268 271
    return soplex->obj(i);
269 272
  }
270 273

	
271 274
  SoplexLp::SolveExitStatus SoplexLp::_solve() {
272 275

	
273 276
    _clear_temporals();
277
    
278
    _applyMessageLevel();
274 279

	
275 280
    soplex::SPxSolver::Status status = soplex->solve();
276 281

	
277 282
    switch (status) {
278 283
    case soplex::SPxSolver::OPTIMAL:
279 284
    case soplex::SPxSolver::INFEASIBLE:
280 285
    case soplex::SPxSolver::UNBOUNDED:
281 286
      return SOLVED;
282 287
    default:
283 288
      return UNSOLVED;
284 289
    }
285 290
  }
286 291

	
287 292
  SoplexLp::Value SoplexLp::_getPrimal(int i) const {
288 293
    if (_primal_values.empty()) {
289 294
      _primal_values.resize(soplex->nCols());
290 295
      soplex::Vector pv(_primal_values.size(), &_primal_values.front());
291 296
      soplex->getPrimal(pv);
292 297
    }
293 298
    return _primal_values[i];
294 299
  }
295 300

	
296 301
  SoplexLp::Value SoplexLp::_getDual(int i) const {
297 302
    if (_dual_values.empty()) {
298 303
      _dual_values.resize(soplex->nRows());
299 304
      soplex::Vector dv(_dual_values.size(), &_dual_values.front());
300 305
      soplex->getDual(dv);
301 306
    }
302 307
    return _dual_values[i];
303 308
  }
304 309

	
305 310
  SoplexLp::Value SoplexLp::_getPrimalValue() const {
306 311
    return soplex->objValue();
307 312
  }
308 313

	
309 314
  SoplexLp::VarStatus SoplexLp::_getColStatus(int i) const {
310 315
    switch (soplex->getBasisColStatus(i)) {
311 316
    case soplex::SPxSolver::BASIC:
312 317
      return BASIC;
313 318
    case soplex::SPxSolver::ON_UPPER:
314 319
      return UPPER;
315 320
    case soplex::SPxSolver::ON_LOWER:
316 321
      return LOWER;
317 322
    case soplex::SPxSolver::FIXED:
318 323
      return FIXED;
319 324
    case soplex::SPxSolver::ZERO:
320 325
      return FREE;
321 326
    default:
... ...
@@ -374,50 +379,74 @@
374 379
  }
375 380

	
376 381
  SoplexLp::ProblemType SoplexLp::_getDualType() const {
377 382
    switch (soplex->status()) {
378 383
    case soplex::SPxSolver::OPTIMAL:
379 384
      return OPTIMAL;
380 385
    case soplex::SPxSolver::UNBOUNDED:
381 386
      return UNBOUNDED;
382 387
    case soplex::SPxSolver::INFEASIBLE:
383 388
      return INFEASIBLE;
384 389
    default:
385 390
      return UNDEFINED;
386 391
    }
387 392
  }
388 393

	
389 394
  void SoplexLp::_setSense(Sense sense) {
390 395
    switch (sense) {
391 396
    case MIN:
392 397
      soplex->changeSense(soplex::SPxSolver::MINIMIZE);
393 398
      break;
394 399
    case MAX:
395 400
      soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
396 401
    }
397 402
  }
398 403

	
399 404
  SoplexLp::Sense SoplexLp::_getSense() const {
400 405
    switch (soplex->spxSense()) {
401 406
    case soplex::SPxSolver::MAXIMIZE:
402 407
      return MAX;
403 408
    case soplex::SPxSolver::MINIMIZE:
404 409
      return MIN;
405 410
    default:
406 411
      LEMON_ASSERT(false, "Wrong sense.");
407 412
      return SoplexLp::Sense();
408 413
    }
409 414
  }
410 415

	
411 416
  void SoplexLp::_clear() {
412 417
    soplex->clear();
413 418
    _col_names.clear();
414 419
    _col_names_ref.clear();
415 420
    _row_names.clear();
416 421
    _row_names_ref.clear();
417 422
    cols.clear();
418 423
    rows.clear();
419 424
    _clear_temporals();
420 425
  }
421 426

	
427
  void SoplexLp::_messageLevel(MessageLevel level) {
428
    switch (level) {
429
    case MESSAGE_NOTHING:
430
      _message_level = -1;
431
      break;
432
    case MESSAGE_ERROR:
433
      _message_level = soplex::SPxOut::ERROR;
434
      break;
435
    case MESSAGE_WARNING:
436
      _message_level = soplex::SPxOut::WARNING;
437
      break;
438
    case MESSAGE_NORMAL:
439
      _message_level = soplex::SPxOut::INFO2;
440
      break;
441
    case MESSAGE_VERBOSE:
442
      _message_level = soplex::SPxOut::DEBUG;
443
      break;
444
    }
445
  }
446

	
447
  void SoplexLp::_applyMessageLevel() {
448
    soplex::Param::setVerbose(_message_level);
449
  }
450

	
422 451
} //namespace lemon
423 452

	
Ignore white space 96 line context
... ...
@@ -99,54 +99,59 @@
99 99
    virtual void _setRowName(int row, const std::string& name);
100 100
    virtual int _rowByName(const std::string& name) const;
101 101

	
102 102
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
103 103
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
104 104

	
105 105
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
106 106
    virtual void _getColCoeffs(int i, InsertIterator b) const;
107 107

	
108 108
    virtual void _setCoeff(int row, int col, Value value);
109 109
    virtual Value _getCoeff(int row, int col) const;
110 110

	
111 111
    virtual void _setColLowerBound(int i, Value value);
112 112
    virtual Value _getColLowerBound(int i) const;
113 113
    virtual void _setColUpperBound(int i, Value value);
114 114
    virtual Value _getColUpperBound(int i) const;
115 115

	
116 116
    virtual void _setRowLowerBound(int i, Value value);
117 117
    virtual Value _getRowLowerBound(int i) const;
118 118
    virtual void _setRowUpperBound(int i, Value value);
119 119
    virtual Value _getRowUpperBound(int i) const;
120 120

	
121 121
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
122 122
    virtual void _getObjCoeffs(InsertIterator b) const;
123 123

	
124 124
    virtual void _setObjCoeff(int i, Value obj_coef);
125 125
    virtual Value _getObjCoeff(int i) const;
126 126

	
127 127
    virtual void _setSense(Sense sense);
128 128
    virtual Sense _getSense() const;
129 129

	
130 130
    virtual SolveExitStatus _solve();
131 131
    virtual Value _getPrimal(int i) const;
132 132
    virtual Value _getDual(int i) const;
133 133

	
134 134
    virtual Value _getPrimalValue() const;
135 135

	
136 136
    virtual Value _getPrimalRay(int i) const;
137 137
    virtual Value _getDualRay(int i) const;
138 138

	
139 139
    virtual VarStatus _getColStatus(int i) const;
140 140
    virtual VarStatus _getRowStatus(int i) const;
141 141

	
142 142
    virtual ProblemType _getPrimalType() const;
143 143
    virtual ProblemType _getDualType() const;
144 144

	
145 145
    virtual void _clear();
146 146

	
147
    void _messageLevel(MessageLevel m);
148
    void _applyMessageLevel();
149

	
150
    int _message_level;
151

	
147 152
  };
148 153

	
149 154
} //END OF NAMESPACE LEMON
150 155

	
151 156
#endif //LEMON_SOPLEX_H
152 157

	
Ignore white space 6 line context
... ...
@@ -350,77 +350,72 @@
350 350
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
351 351

	
352 352
  //Erase one constraint and return to maximization
353 353
  lp.erase(upright);
354 354
  lp.sense(lp.MAX);
355 355
  expected_opt=LpSolver::INF;
356 356
  solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
357 357

	
358 358
  //Infeasibilty
359 359
  lp.addRow(x1+x2 <=-2);
360 360
  solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
361 361

	
362 362
}
363 363

	
364 364
template<class LP>
365 365
void cloneTest()
366 366
{
367 367
  //Test for clone/new
368 368

	
369 369
  LP* lp = new LP();
370 370
  LP* lpnew = lp->newSolver();
371 371
  LP* lpclone = lp->cloneSolver();
372 372
  delete lp;
373 373
  delete lpnew;
374 374
  delete lpclone;
375 375
}
376 376

	
377 377
int main()
378 378
{
379 379
  LpSkeleton lp_skel;
380 380
  lpTest(lp_skel);
381 381

	
382 382
#ifdef HAVE_GLPK
383 383
  {
384 384
    GlpkLp lp_glpk1,lp_glpk2;
385 385
    lpTest(lp_glpk1);
386 386
    aTest(lp_glpk2);
387 387
    cloneTest<GlpkLp>();
388 388
  }
389 389
#endif
390 390

	
391 391
#ifdef HAVE_CPLEX
392 392
  try {
393 393
    CplexLp lp_cplex1,lp_cplex2;
394 394
    lpTest(lp_cplex1);
395 395
    aTest(lp_cplex2);
396 396
    cloneTest<CplexLp>();
397 397
  } catch (CplexEnv::LicenseError& error) {
398
#ifdef LEMON_FORCE_CPLEX_CHECK
399 398
    check(false, error.what());
400
#else
401
    std::cerr << error.what() << std::endl;
402
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
403
#endif
404 399
  }
405 400
#endif
406 401

	
407 402
#ifdef HAVE_SOPLEX
408 403
  {
409 404
    SoplexLp lp_soplex1,lp_soplex2;
410 405
    lpTest(lp_soplex1);
411 406
    aTest(lp_soplex2);
412 407
    cloneTest<SoplexLp>();
413 408
  }
414 409
#endif
415 410

	
416 411
#ifdef HAVE_CLP
417 412
  {
418 413
    ClpLp lp_clp1,lp_clp2;
419 414
    lpTest(lp_clp1);
420 415
    aTest(lp_clp2);
421 416
    cloneTest<ClpLp>();
422 417
  }
423 418
#endif
424 419

	
425 420
  return 0;
426 421
}
Ignore white space 6 line context
... ...
@@ -98,68 +98,63 @@
98 98
  mip.colType(x2,MipSolver::INTEGER);
99 99
  expected_opt=1.0/2.0;
100 100
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
101 101

	
102 102

	
103 103
  //Restrict both to integer
104 104
  mip.colType(x1,MipSolver::INTEGER);
105 105
  expected_opt=0;
106 106
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
107 107

	
108 108
  //Erase a variable
109 109
  mip.erase(x2);
110 110
  mip.rowUpperBound(y2, 8);
111 111
  expected_opt=1;
112 112
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
113 113

	
114 114
}
115 115

	
116 116

	
117 117
template<class MIP>
118 118
void cloneTest()
119 119
{
120 120

	
121 121
  MIP* mip = new MIP();
122 122
  MIP* mipnew = mip->newSolver();
123 123
  MIP* mipclone = mip->cloneSolver();
124 124
  delete mip;
125 125
  delete mipnew;
126 126
  delete mipclone;
127 127
}
128 128

	
129 129
int main()
130 130
{
131 131

	
132 132
#ifdef HAVE_GLPK
133 133
  {
134 134
    GlpkMip mip1;
135 135
    aTest(mip1);
136 136
    cloneTest<GlpkMip>();
137 137
  }
138 138
#endif
139 139

	
140 140
#ifdef HAVE_CPLEX
141 141
  try {
142 142
    CplexMip mip2;
143 143
    aTest(mip2);
144 144
    cloneTest<CplexMip>();
145 145
  } catch (CplexEnv::LicenseError& error) {
146
#ifdef LEMON_FORCE_CPLEX_CHECK
147 146
    check(false, error.what());
148
#else
149
    std::cerr << error.what() << std::endl;
150
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
151
#endif
152 147
  }
153 148
#endif
154 149

	
155 150
#ifdef HAVE_CBC
156 151
  {
157 152
    CbcMip mip1;
158 153
    aTest(mip1);
159 154
    cloneTest<CbcMip>();
160 155
  }
161 156
#endif
162 157

	
163 158
  return 0;
164 159

	
165 160
}
Ignore white space 6 line context
... ...
@@ -44,82 +44,86 @@
44 44
        -e "s/Edge/_Ar_c_label_/g"\
45 45
        -e "s/edge/_ar_c_label_/g"\
46 46
        -e "s/A[Nn]ode/_Re_d_label_/g"\
47 47
        -e "s/B[Nn]ode/_Blu_e_label_/g"\
48 48
        -e "s/A-[Nn]ode/_Re_d_label_/g"\
49 49
        -e "s/B-[Nn]ode/_Blu_e_label_/g"\
50 50
        -e "s/a[Nn]ode/_re_d_label_/g"\
51 51
        -e "s/b[Nn]ode/_blu_e_label_/g"\
52 52
        -e "s/\<UGRAPH_TYPEDEFS\([ \t]*([ \t]*\)typename[ \t]/TEMPLATE__GR_APH_TY_PEDE_FS_label_\1/g"\
53 53
        -e "s/\<GRAPH_TYPEDEFS\([ \t]*([ \t]*\)typename[ \t]/TEMPLATE__DIGR_APH_TY_PEDE_FS_label_\1/g"\
54 54
        -e "s/\<UGRAPH_TYPEDEFS\>/_GR_APH_TY_PEDE_FS_label_/g"\
55 55
        -e "s/\<GRAPH_TYPEDEFS\>/_DIGR_APH_TY_PEDE_FS_label_/g"\
56 56
        -e "s/_Digr_aph_label_/Digraph/g"\
57 57
        -e "s/_digr_aph_label_/digraph/g"\
58 58
        -e "s/_Gr_aph_label_/Graph/g"\
59 59
        -e "s/_gr_aph_label_/graph/g"\
60 60
        -e "s/_Ar_c_label_/Arc/g"\
61 61
        -e "s/_ar_c_label_/arc/g"\
62 62
        -e "s/_Ed_ge_label_/Edge/g"\
63 63
        -e "s/_ed_ge_label_/edge/g"\
64 64
        -e "s/_In_cEd_geIt_label_/IncEdgeIt/g"\
65 65
        -e "s/_Re_d_label_/Red/g"\
66 66
        -e "s/_Blu_e_label_/Blue/g"\
67 67
        -e "s/_re_d_label_/red/g"\
68 68
        -e "s/_blu_e_label_/blue/g"\
69 69
        -e "s/_GR_APH_TY_PEDE_FS_label_/GRAPH_TYPEDEFS/g"\
70 70
        -e "s/_DIGR_APH_TY_PEDE_FS_label_/DIGRAPH_TYPEDEFS/g"\
71 71
        -e "s/DigraphToEps/GraphToEps/g"\
72 72
        -e "s/digraphToEps/graphToEps/g"\
73 73
        -e "s/\<DefPredMap\>/SetPredMap/g"\
74 74
        -e "s/\<DefDistMap\>/SetDistMap/g"\
75 75
        -e "s/\<DefReachedMap\>/SetReachedMap/g"\
76 76
        -e "s/\<DefProcessedMap\>/SetProcessedMap/g"\
77 77
        -e "s/\<DefHeap\>/SetHeap/g"\
78 78
        -e "s/\<DefStandardHeap\>/SetStandradHeap/g"\
79 79
        -e "s/\<DefOperationTraits\>/SetOperationTraits/g"\
80 80
        -e "s/\<DefProcessedMapToBeDefaultMap\>/SetStandardProcessedMap/g"\
81 81
        -e "s/\<copyGraph\>/graphCopy/g"\
82 82
        -e "s/\<copyDigraph\>/digraphCopy/g"\
83 83
        -e "s/\<HyperCubeDigraph\>/HypercubeGraph/g"\
84 84
        -e "s/\<IntegerMap\>/RangeMap/g"\
85 85
        -e "s/\<integerMap\>/rangeMap/g"\
86 86
        -e "s/\<\([sS]\)tdMap\>/\1parseMap/g"\
87 87
        -e "s/\<\([Ff]\)unctorMap\>/\1unctorToMap/g"\
88 88
        -e "s/\<\([Mm]\)apFunctor\>/\1apToFunctor/g"\
89 89
        -e "s/\<\([Ff]\)orkWriteMap\>/\1orkMap/g"\
90 90
        -e "s/\<StoreBoolMap\>/LoggerBoolMap/g"\
91 91
        -e "s/\<storeBoolMap\>/loggerBoolMap/g"\
92
        -e "s/\<InvertableMap\>/CrossRefMap/g"\
93
        -e "s/\<invertableMap\>/crossRefMap/g"\
94
        -e "s/\<DescriptorMap\>/RangeIdMap/g"\
95
        -e "s/\<descriptorMap\>/rangeIdMap/g"\
92 96
        -e "s/\<BoundingBox\>/Box/g"\
93 97
        -e "s/\<readNauty\>/readNautyGraph/g"\
94 98
        -e "s/\<RevDigraphAdaptor\>/ReverseDigraph/g"\
95 99
        -e "s/\<revDigraphAdaptor\>/reverseDigraph/g"\
96 100
        -e "s/\<SubDigraphAdaptor\>/SubDigraph/g"\
97 101
        -e "s/\<subDigraphAdaptor\>/subDigraph/g"\
98 102
        -e "s/\<SubGraphAdaptor\>/SubGraph/g"\
99 103
        -e "s/\<subGraphAdaptor\>/subGraph/g"\
100 104
        -e "s/\<NodeSubDigraphAdaptor\>/FilterNodes/g"\
101 105
        -e "s/\<nodeSubDigraphAdaptor\>/filterNodes/g"\
102 106
        -e "s/\<ArcSubDigraphAdaptor\>/FilterArcs/g"\
103 107
        -e "s/\<arcSubDigraphAdaptor\>/filterArcs/g"\
104 108
        -e "s/\<UndirDigraphAdaptor\>/Undirector/g"\
105 109
        -e "s/\<undirDigraphAdaptor\>/undirector/g"\
106 110
        -e "s/\<ResDigraphAdaptor\>/ResidualDigraph/g"\
107 111
        -e "s/\<resDigraphAdaptor\>/residualDigraph/g"\
108 112
        -e "s/\<SplitDigraphAdaptor\>/SplitNodes/g"\
109 113
        -e "s/\<splitDigraphAdaptor\>/splitNodes/g"\
110 114
        -e "s/\<SubGraphAdaptor\>/SubGraph/g"\
111 115
        -e "s/\<subGraphAdaptor\>/subGraph/g"\
112 116
        -e "s/\<NodeSubGraphAdaptor\>/FilterNodes/g"\
113 117
        -e "s/\<nodeSubGraphAdaptor\>/filterNodes/g"\
114 118
        -e "s/\<ArcSubGraphAdaptor\>/FilterEdges/g"\
115 119
        -e "s/\<arcSubGraphAdaptor\>/filterEdges/g"\
116 120
        -e "s/\<DirGraphAdaptor\>/Orienter/g"\
117 121
        -e "s/\<dirGraphAdaptor\>/orienter/g"\
118 122
        -e "s/\<LpCplex\>/CplexLp/g"\
119 123
        -e "s/\<MipCplex\>/CplexMip/g"\
120 124
        -e "s/\<LpGlpk\>/GlpkLp/g"\
121 125
        -e "s/\<MipGlpk\>/GlpkMip/g"\
122 126
        -e "s/\<LpSoplex\>/SoplexLp/g"\
123 127
    <$i > $TMP
124 128
    mv $TMP $i
125 129
done
0 comments (0 inline)