↑ Collapse diff ↑
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 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 {
112 115
    name = _prob->getColumnName(c);
113 116
  }
114 117

	
115 118
  void CbcMip::_setColName(int c, const std::string& name) {
116 119
    _prob->setColumnName(c, name.c_str());
117 120
  }
118 121

	
119 122
  int CbcMip::_colByName(const std::string& name) const {
120 123
    return _prob->column(name.c_str());
121 124
  }
122 125

	
123 126
  void CbcMip::_getRowName(int r, std::string& name) const {
124 127
    name = _prob->getRowName(r);
125 128
  }
126 129

	
127 130
  void CbcMip::_setRowName(int r, const std::string& name) {
128 131
    _prob->setRowName(r, name.c_str());
129 132
  }
130 133

	
131 134
  int CbcMip::_rowByName(const std::string& name) const {
132 135
    return _prob->row(name.c_str());
133 136
  }
134 137

	
135 138
  void CbcMip::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
136 139
    for (ExprIterator it = b; it != e; ++it) {
137 140
      _prob->setElement(i, it->first, it->second);
138 141
    }
139 142
  }
140 143

	
141 144
  void CbcMip::_getRowCoeffs(int ix, InsertIterator b) const {
142 145
    int length = _prob->numberRows();
143 146

	
144 147
    std::vector<int> indices(length);
145 148
    std::vector<Value> values(length);
146 149

	
147 150
    length = _prob->getRow(ix, &indices[0], &values[0]);
148 151

	
149 152
    for (int i = 0; i < length; ++i) {
150 153
      *b = std::make_pair(indices[i], values[i]);
151 154
      ++b;
152 155
    }
153 156
  }
154 157

	
155 158
  void CbcMip::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
156 159
    for (ExprIterator it = b; it != e; ++it) {
157 160
      _prob->setElement(it->first, ix, it->second);
158 161
    }
159 162
  }
160 163

	
161 164
  void CbcMip::_getColCoeffs(int ix, InsertIterator b) const {
162 165
    int length = _prob->numberColumns();
163 166

	
164 167
    std::vector<int> indices(length);
165 168
    std::vector<Value> values(length);
166 169

	
167 170
    length = _prob->getColumn(ix, &indices[0], &values[0]);
168 171

	
169 172
    for (int i = 0; i < length; ++i) {
170 173
      *b = std::make_pair(indices[i], values[i]);
171 174
      ++b;
172 175
    }
173 176
  }
174 177

	
175 178
  void CbcMip::_setCoeff(int ix, int jx, Value value) {
176 179
    _prob->setElement(ix, jx, value);
177 180
  }
178 181

	
179 182
  CbcMip::Value CbcMip::_getCoeff(int ix, int jx) const {
180 183
    return _prob->getElement(ix, jx);
181 184
  }
182 185

	
183 186

	
184 187
  void CbcMip::_setColLowerBound(int i, Value lo) {
185 188
    LEMON_ASSERT(lo != INF, "Invalid bound");
186 189
    _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
187 190
  }
188 191

	
189 192
  CbcMip::Value CbcMip::_getColLowerBound(int i) const {
190 193
    double val = _prob->getColumnLower(i);
191 194
    return val == - COIN_DBL_MAX ? - INF : val;
192 195
  }
193 196

	
194 197
  void CbcMip::_setColUpperBound(int i, Value up) {
195 198
    LEMON_ASSERT(up != -INF, "Invalid bound");
196 199
    _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
197 200
  }
198 201

	
199 202
  CbcMip::Value CbcMip::_getColUpperBound(int i) const {
200 203
    double val = _prob->getColumnUpper(i);
201 204
    return val == COIN_DBL_MAX ? INF : val;
202 205
  }
203 206

	
204 207
  void CbcMip::_setRowLowerBound(int i, Value lo) {
205 208
    LEMON_ASSERT(lo != INF, "Invalid bound");
206 209
    _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
207 210
  }
208 211

	
209 212
  CbcMip::Value CbcMip::_getRowLowerBound(int i) const {
210 213
    double val = _prob->getRowLower(i);
211 214
    return val == - COIN_DBL_MAX ? - INF : val;
212 215
  }
213 216

	
214 217
  void CbcMip::_setRowUpperBound(int i, Value up) {
215 218
    LEMON_ASSERT(up != -INF, "Invalid bound");
216 219
    _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
217 220
  }
218 221

	
219 222
  CbcMip::Value CbcMip::_getRowUpperBound(int i) const {
220 223
    double val = _prob->getRowUpper(i);
221 224
    return val == COIN_DBL_MAX ? INF : val;
222 225
  }
223 226

	
224 227
  void CbcMip::_setObjCoeffs(ExprIterator b, ExprIterator e) {
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
339 326

	
340 327
      CbcRounding heuristic1(*_cbc_model);
341 328
      heuristic1.setWhen(3);
342 329
      _cbc_model->addHeuristic(&heuristic1);
343 330

	
344 331
      CbcHeuristicLocal heuristic2(*_cbc_model);
345 332
      heuristic2.setWhen(3);
346 333
      _cbc_model->addHeuristic(&heuristic2);
347 334

	
348 335
      CbcHeuristicGreedyCover heuristic3(*_cbc_model);
349 336
      heuristic3.setAlgorithm(11);
350 337
      heuristic3.setWhen(3);
351 338
      _cbc_model->addHeuristic(&heuristic3);
352 339

	
353 340
      CbcHeuristicFPump heuristic4(*_cbc_model);
354 341
      heuristic4.setWhen(3);
355 342
      _cbc_model->addHeuristic(&heuristic4);
356 343

	
357 344
      CbcHeuristicRINS heuristic5(*_cbc_model);
358 345
      heuristic5.setWhen(3);
359 346
      _cbc_model->addHeuristic(&heuristic5);
360 347

	
361 348
      if (_cbc_model->getNumCols() < 500) {
362 349
        _cbc_model->setMaximumCutPassesAtRoot(-100);
363 350
      } else if (_cbc_model->getNumCols() < 5000) {
364 351
        _cbc_model->setMaximumCutPassesAtRoot(100);
365 352
      } else {
366 353
        _cbc_model->setMaximumCutPassesAtRoot(20);
367 354
      }
368 355

	
369 356
      if (_cbc_model->getNumCols() < 5000) {
370 357
        _cbc_model->setNumberStrong(10);
371 358
      }
372 359

	
373 360
      _cbc_model->solver()->setIntParam(OsiMaxNumIterationHotStart, 100);
374 361
      _cbc_model->branchAndBound();
375 362
    }
376 363

	
377 364
    if (_cbc_model->isAbandoned()) {
378 365
      return UNSOLVED;
379 366
    } else {
380 367
      return SOLVED;
381 368
    }
382 369
  }
383 370

	
384 371
  CbcMip::Value CbcMip::_getSol(int i) const {
385 372
    return _cbc_model->getColSolution()[i];
386 373
  }
387 374

	
388 375
  CbcMip::Value CbcMip::_getSolValue() const {
389 376
    return _cbc_model->getObjValue();
390 377
  }
391 378

	
392 379
  CbcMip::ProblemType CbcMip::_getType() const {
393 380
    if (_cbc_model->isProvenOptimal()) {
394 381
      return OPTIMAL;
395 382
    } else if (_cbc_model->isContinuousUnbounded()) {
396 383
      return UNBOUNDED;
397 384
    }
398 385
    return FEASIBLE;
399 386
  }
400 387

	
401 388
  void CbcMip::_setSense(Sense sense) {
402 389
    switch (sense) {
403 390
    case MIN:
404 391
      _prob->setOptimizationDirection(1.0);
405 392
      break;
406 393
    case MAX:
407 394
      _prob->setOptimizationDirection(- 1.0);
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
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
// -*- C++ -*-
20 20
#ifndef LEMON_CBC_H
21 21
#define LEMON_CBC_H
22 22

	
23 23
///\file
24 24
///\brief Header of the LEMON-CBC mip solver interface.
25 25
///\ingroup lp_group
26 26

	
27 27
#include <lemon/lp_base.h>
28 28

	
29 29
class CoinModel;
30 30
class OsiSolverInterface;
31 31
class CbcModel;
32 32

	
33 33
namespace lemon {
34 34

	
35 35
  /// \brief Interface for the CBC MIP solver
36 36
  ///
37 37
  /// This class implements an interface for the CBC MIP solver.
38 38
  ///\ingroup lp_group
39 39
  class CbcMip : public MipSolver {
40 40
  protected:
41 41

	
42 42
    CoinModel *_prob;
43 43
    OsiSolverInterface *_osi_solver;
44 44
    CbcModel *_cbc_model;
45 45

	
46 46
  public:
47 47

	
48 48
    /// \e
49 49
    CbcMip();
50 50
    /// \e
51 51
    CbcMip(const CbcMip&);
52 52
    /// \e
53 53
    ~CbcMip();
54 54
    /// \e
55 55
    virtual CbcMip* newSolver() const;
56 56
    /// \e
57 57
    virtual CbcMip* cloneSolver() const;
58 58

	
59 59
  protected:
60 60

	
61 61
    virtual const char* _solverName() const;
62 62

	
63 63
    virtual int _addCol();
64 64
    virtual int _addRow();
65 65

	
66 66
    virtual void _eraseCol(int i);
67 67
    virtual void _eraseRow(int i);
68 68

	
69 69
    virtual void _eraseColId(int i);
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));
84 84
    _prob->deleteColumns(1, &c);
85 85
  }
86 86

	
87 87
  void ClpLp::_eraseRow(int r) {
88 88
    _row_names_ref.erase(_prob->getRowName(r));
89 89
    _prob->deleteRows(1, &r);
90 90
  }
91 91

	
92 92
  void ClpLp::_eraseColId(int i) {
93 93
    cols.eraseIndex(i);
94 94
    cols.shiftIndices(i);
95 95
  }
96 96

	
97 97
  void ClpLp::_eraseRowId(int i) {
98 98
    rows.eraseIndex(i);
99 99
    rows.shiftIndices(i);
100 100
  }
101 101

	
102 102
  void ClpLp::_getColName(int c, std::string& name) const {
103 103
    name = _prob->getColumnName(c);
104 104
  }
105 105

	
106 106
  void ClpLp::_setColName(int c, const std::string& name) {
107 107
    _prob->setColumnName(c, const_cast<std::string&>(name));
108 108
    _col_names_ref[name] = c;
109 109
  }
110 110

	
111 111
  int ClpLp::_colByName(const std::string& name) const {
112 112
    std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
113 113
    return it != _col_names_ref.end() ? it->second : -1;
114 114
  }
115 115

	
116 116
  void ClpLp::_getRowName(int r, std::string& name) const {
117 117
    name = _prob->getRowName(r);
118 118
  }
119 119

	
120 120
  void ClpLp::_setRowName(int r, const std::string& name) {
121 121
    _prob->setRowName(r, const_cast<std::string&>(name));
122 122
    _row_names_ref[name] = r;
123 123
  }
124 124

	
125 125
  int ClpLp::_rowByName(const std::string& name) const {
126 126
    std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
127 127
    return it != _row_names_ref.end() ? it->second : -1;
128 128
  }
129 129

	
130 130

	
131 131
  void ClpLp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
132 132
    std::map<int, Value> coeffs;
133 133

	
134 134
    int n = _prob->clpMatrix()->getNumCols();
135 135

	
136 136
    const int* indices = _prob->clpMatrix()->getIndices();
137 137
    const double* elements = _prob->clpMatrix()->getElements();
138 138

	
139 139
    for (int i = 0; i < n; ++i) {
140 140
      CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
141 141
      CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
142 142

	
143 143
      const int* it = std::lower_bound(indices + begin, indices + end, ix);
144 144
      if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
145 145
        coeffs[i] = 0.0;
146 146
      }
147 147
    }
148 148

	
149 149
    for (ExprIterator it = b; it != e; ++it) {
150 150
      coeffs[it->first] = it->second;
151 151
    }
152 152

	
153 153
    for (std::map<int, Value>::iterator it = coeffs.begin();
154 154
         it != coeffs.end(); ++it) {
155 155
      _prob->modifyCoefficient(ix, it->first, it->second);
156 156
    }
157 157
  }
158 158

	
159 159
  void ClpLp::_getRowCoeffs(int ix, InsertIterator b) const {
160 160
    int n = _prob->clpMatrix()->getNumCols();
161 161

	
162 162
    const int* indices = _prob->clpMatrix()->getIndices();
163 163
    const double* elements = _prob->clpMatrix()->getElements();
164 164

	
165 165
    for (int i = 0; i < n; ++i) {
166 166
      CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
167 167
      CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
168 168

	
169 169
      const int* it = std::lower_bound(indices + begin, indices + end, ix);
170 170
      if (it != indices + end && *it == ix) {
171 171
        *b = std::make_pair(i, elements[it - indices]);
172 172
      }
173 173
    }
174 174
  }
175 175

	
176 176
  void ClpLp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
177 177
    std::map<int, Value> coeffs;
178 178

	
179 179
    CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
180 180
    CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
181 181

	
182 182
    const int* indices = _prob->clpMatrix()->getIndices();
183 183
    const double* elements = _prob->clpMatrix()->getElements();
184 184

	
185 185
    for (CoinBigIndex i = begin; i != end; ++i) {
186 186
      if (elements[i] != 0.0) {
187 187
        coeffs[indices[i]] = 0.0;
188 188
      }
189 189
    }
190 190
    for (ExprIterator it = b; it != e; ++it) {
191 191
      coeffs[it->first] = it->second;
192 192
    }
193 193
    for (std::map<int, Value>::iterator it = coeffs.begin();
194 194
         it != coeffs.end(); ++it) {
195 195
      _prob->modifyCoefficient(it->first, ix, it->second);
196 196
    }
197 197
  }
198 198

	
199 199
  void ClpLp::_getColCoeffs(int ix, InsertIterator b) const {
200 200
    CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
201 201
    CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
202 202

	
203 203
    const int* indices = _prob->clpMatrix()->getIndices();
204 204
    const double* elements = _prob->clpMatrix()->getElements();
205 205

	
206 206
    for (CoinBigIndex i = begin; i != end; ++i) {
207 207
      *b = std::make_pair(indices[i], elements[i]);
208 208
      ++b;
209 209
    }
210 210
  }
211 211

	
212 212
  void ClpLp::_setCoeff(int ix, int jx, Value value) {
213 213
    _prob->modifyCoefficient(ix, jx, value);
214 214
  }
215 215

	
216 216
  ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const {
217 217
    CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
218 218
    CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
219 219

	
220 220
    const int* indices = _prob->clpMatrix()->getIndices();
221 221
    const double* elements = _prob->clpMatrix()->getElements();
222 222

	
223 223
    const int* it = std::lower_bound(indices + begin, indices + end, jx);
224 224
    if (it != indices + end && *it == jx) {
225 225
      return elements[it - indices];
226 226
    } else {
227 227
      return 0.0;
228 228
    }
229 229
  }
230 230

	
231 231
  void ClpLp::_setColLowerBound(int i, Value lo) {
232 232
    _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
233 233
  }
234 234

	
235 235
  ClpLp::Value ClpLp::_getColLowerBound(int i) const {
236 236
    double val = _prob->getColLower()[i];
237 237
    return val == - COIN_DBL_MAX ? - INF : val;
238 238
  }
239 239

	
240 240
  void ClpLp::_setColUpperBound(int i, Value up) {
241 241
    _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
242 242
  }
243 243

	
244 244
  ClpLp::Value ClpLp::_getColUpperBound(int i) const {
245 245
    double val = _prob->getColUpper()[i];
246 246
    return val == COIN_DBL_MAX ? INF : val;
247 247
  }
248 248

	
249 249
  void ClpLp::_setRowLowerBound(int i, Value lo) {
250 250
    _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
251 251
  }
252 252

	
253 253
  ClpLp::Value ClpLp::_getRowLowerBound(int i) const {
254 254
    double val = _prob->getRowLower()[i];
255 255
    return val == - COIN_DBL_MAX ? - INF : val;
256 256
  }
257 257

	
258 258
  void ClpLp::_setRowUpperBound(int i, Value up) {
259 259
    _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
260 260
  }
261 261

	
262 262
  ClpLp::Value ClpLp::_getRowUpperBound(int i) const {
263 263
    double val = _prob->getRowUpper()[i];
264 264
    return val == COIN_DBL_MAX ? INF : val;
265 265
  }
266 266

	
267 267
  void ClpLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
268 268
    int num = _prob->clpMatrix()->getNumCols();
269 269
    for (int i = 0; i < num; ++i) {
270 270
      _prob->setObjectiveCoefficient(i, 0.0);
271 271
    }
272 272
    for (ExprIterator it = b; it != e; ++it) {
273 273
      _prob->setObjectiveCoefficient(it->first, it->second);
274 274
    }
275 275
  }
276 276

	
277 277
  void ClpLp::_getObjCoeffs(InsertIterator b) const {
278 278
    int num = _prob->clpMatrix()->getNumCols();
279 279
    for (int i = 0; i < num; ++i) {
280 280
      Value coef = _prob->getObjCoefficients()[i];
281 281
      if (coef != 0.0) {
282 282
        *b = std::make_pair(i, coef);
283 283
        ++b;
284 284
      }
285 285
    }
286 286
  }
287 287

	
288 288
  void ClpLp::_setObjCoeff(int i, Value obj_coef) {
289 289
    _prob->setObjectiveCoefficient(i, obj_coef);
290 290
  }
291 291

	
292 292
  ClpLp::Value ClpLp::_getObjCoeff(int i) const {
293 293
    return _prob->getObjCoefficients()[i];
294 294
  }
295 295

	
296 296
  ClpLp::SolveExitStatus ClpLp::_solve() {
297 297
    return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
298 298
  }
299 299

	
300 300
  ClpLp::SolveExitStatus ClpLp::solvePrimal() {
301 301
    return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
302 302
  }
303 303

	
304 304
  ClpLp::SolveExitStatus ClpLp::solveDual() {
305 305
    return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
306 306
  }
307 307

	
308 308
  ClpLp::SolveExitStatus ClpLp::solveBarrier() {
309 309
    return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
310 310
  }
311 311

	
312 312
  ClpLp::Value ClpLp::_getPrimal(int i) const {
313 313
    return _prob->primalColumnSolution()[i];
314 314
  }
315 315
  ClpLp::Value ClpLp::_getPrimalValue() const {
316 316
    return _prob->objectiveValue();
317 317
  }
318 318

	
319 319
  ClpLp::Value ClpLp::_getDual(int i) const {
320 320
    return _prob->dualRowSolution()[i];
321 321
  }
322 322

	
323 323
  ClpLp::Value ClpLp::_getPrimalRay(int i) const {
324 324
    if (!_primal_ray) {
325 325
      _primal_ray = _prob->unboundedRay();
326 326
      LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
327 327
    }
328 328
    return _primal_ray[i];
329 329
  }
330 330

	
331 331
  ClpLp::Value ClpLp::_getDualRay(int i) const {
332 332
    if (!_dual_ray) {
333 333
      _dual_ray = _prob->infeasibilityRay();
334 334
      LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
335 335
    }
336 336
    return _dual_ray[i];
337 337
  }
338 338

	
339 339
  ClpLp::VarStatus ClpLp::_getColStatus(int i) const {
340 340
    switch (_prob->getColumnStatus(i)) {
341 341
    case ClpSimplex::basic:
342 342
      return BASIC;
343 343
    case ClpSimplex::isFree:
344 344
      return FREE;
345 345
    case ClpSimplex::atUpperBound:
346 346
      return UPPER;
347 347
    case ClpSimplex::atLowerBound:
348 348
      return LOWER;
349 349
    case ClpSimplex::isFixed:
350 350
      return FIXED;
351 351
    case ClpSimplex::superBasic:
352 352
      return FREE;
353 353
    default:
354 354
      LEMON_ASSERT(false, "Wrong column status");
355 355
      return VarStatus();
356 356
    }
357 357
  }
358 358

	
359 359
  ClpLp::VarStatus ClpLp::_getRowStatus(int i) const {
360 360
    switch (_prob->getColumnStatus(i)) {
361 361
    case ClpSimplex::basic:
362 362
      return BASIC;
363 363
    case ClpSimplex::isFree:
364 364
      return FREE;
365 365
    case ClpSimplex::atUpperBound:
366 366
      return UPPER;
367 367
    case ClpSimplex::atLowerBound:
368 368
      return LOWER;
369 369
    case ClpSimplex::isFixed:
370 370
      return FIXED;
371 371
    case ClpSimplex::superBasic:
372 372
      return FREE;
373 373
    default:
374 374
      LEMON_ASSERT(false, "Wrong row status");
375 375
      return VarStatus();
376 376
    }
377 377
  }
378 378

	
379 379

	
380 380
  ClpLp::ProblemType ClpLp::_getPrimalType() const {
381 381
    if (_prob->isProvenOptimal()) {
382 382
      return OPTIMAL;
383 383
    } else if (_prob->isProvenPrimalInfeasible()) {
384 384
      return INFEASIBLE;
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
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
#ifndef LEMON_CLP_H
20 20
#define LEMON_CLP_H
21 21

	
22 22
///\file
23 23
///\brief Header of the LEMON-CLP lp solver interface.
24 24

	
25 25
#include <vector>
26 26
#include <string>
27 27

	
28 28
#include <lemon/lp_base.h>
29 29

	
30 30
class ClpSimplex;
31 31

	
32 32
namespace lemon {
33 33

	
34 34
  /// \ingroup lp_group
35 35
  ///
36 36
  /// \brief Interface for the CLP solver
37 37
  ///
38 38
  /// This class implements an interface for the Clp LP solver.  The
39 39
  /// Clp library is an object oriented lp solver library developed at
40 40
  /// the IBM. The CLP is part of the COIN-OR package and it can be
41 41
  /// used with Common Public License.
42 42
  class ClpLp : public LpSolver {
43 43
  protected:
44 44

	
45 45
    ClpSimplex* _prob;
46 46

	
47 47
    std::map<std::string, int> _col_names_ref;
48 48
    std::map<std::string, int> _row_names_ref;
49 49

	
50 50
  public:
51 51

	
52 52
    /// \e
53 53
    ClpLp();
54 54
    /// \e
55 55
    ClpLp(const ClpLp&);
56 56
    /// \e
57 57
    ~ClpLp();
58 58

	
59 59
    /// \e
60 60
    virtual ClpLp* newSolver() const;
61 61
    /// \e
62 62
    virtual ClpLp* cloneSolver() const;
63 63

	
64 64
  protected:
65 65

	
66 66
    mutable double* _primal_ray;
67 67
    mutable double* _dual_ray;
68 68

	
69 69
    void _init_temporals();
70 70
    void _clear_temporals();
71 71

	
72 72
  protected:
73 73

	
74 74
    virtual const char* _solverName() const;
75 75

	
76 76
    virtual int _addCol();
77 77
    virtual int _addRow();
78 78

	
79 79
    virtual void _eraseCol(int i);
80 80
    virtual void _eraseRow(int i);
81 81

	
82 82
    virtual void _eraseColId(int i);
83 83
    virtual void _eraseRowId(int i);
84 84

	
85 85
    virtual void _getColName(int col, std::string& name) const;
86 86
    virtual void _setColName(int col, const std::string& name);
87 87
    virtual int _colByName(const std::string& name) const;
88 88

	
89 89
    virtual void _getRowName(int row, std::string& name) const;
90 90
    virtual void _setRowName(int row, const std::string& name);
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
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
#include <iostream>
20 20
#include <vector>
21 21
#include <cstring>
22 22

	
23 23
#include <lemon/cplex.h>
24 24

	
25 25
extern "C" {
26 26
#include <ilcplex/cplex.h>
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

	
137 140
    size *= -1;
138 141
    std::vector<char> buf(size);
139 142
    char *cname;
140 143
    int tmp;
141 144
    CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
142 145
                  &tmp, col, col);
143 146
    name = cname;
144 147
  }
145 148

	
146 149
  void CplexBase::_setColName(int col, const std::string &name) {
147 150
    char *cname;
148 151
    cname = const_cast<char*>(name.c_str());
149 152
    CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
150 153
  }
151 154

	
152 155
  int CplexBase::_colByName(const std::string& name) const {
153 156
    int index;
154 157
    if (CPXgetcolindex(cplexEnv(), _prob,
155 158
                       const_cast<char*>(name.c_str()), &index) == 0) {
156 159
      return index;
157 160
    }
158 161
    return -1;
159 162
  }
160 163

	
161 164
  void CplexBase::_getRowName(int row, std::string &name) const {
162 165
    int size;
163 166
    CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
164 167
    if (size == 0) {
165 168
      name.clear();
166 169
      return;
167 170
    }
168 171

	
169 172
    size *= -1;
170 173
    std::vector<char> buf(size);
171 174
    char *cname;
172 175
    int tmp;
173 176
    CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
174 177
                  &tmp, row, row);
175 178
    name = cname;
176 179
  }
177 180

	
178 181
  void CplexBase::_setRowName(int row, const std::string &name) {
179 182
    char *cname;
180 183
    cname = const_cast<char*>(name.c_str());
181 184
    CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
182 185
  }
183 186

	
184 187
  int CplexBase::_rowByName(const std::string& name) const {
185 188
    int index;
186 189
    if (CPXgetrowindex(cplexEnv(), _prob,
187 190
                       const_cast<char*>(name.c_str()), &index) == 0) {
188 191
      return index;
189 192
    }
190 193
    return -1;
191 194
  }
192 195

	
193 196
  void CplexBase::_setRowCoeffs(int i, ExprIterator b,
194 197
                                      ExprIterator e)
195 198
  {
196 199
    std::vector<int> indices;
197 200
    std::vector<int> rowlist;
198 201
    std::vector<Value> values;
199 202

	
200 203
    for(ExprIterator it=b; it!=e; ++it) {
201 204
      indices.push_back(it->first);
202 205
      values.push_back(it->second);
203 206
      rowlist.push_back(i);
204 207
    }
205 208

	
206 209
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
207 210
                   &rowlist.front(), &indices.front(), &values.front());
208 211
  }
209 212

	
210 213
  void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
211 214
    int tmp1, tmp2, tmp3, length;
212 215
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
213 216

	
214 217
    length = -length;
215 218
    std::vector<int> indices(length);
216 219
    std::vector<double> values(length);
217 220

	
218 221
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
219 222
               &indices.front(), &values.front(),
220 223
               length, &tmp3, i, i);
221 224

	
222 225
    for (int i = 0; i < length; ++i) {
223 226
      *b = std::make_pair(indices[i], values[i]);
224 227
      ++b;
225 228
    }
226 229
  }
227 230

	
228 231
  void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
229 232
    std::vector<int> indices;
230 233
    std::vector<int> collist;
231 234
    std::vector<Value> values;
232 235

	
233 236
    for(ExprIterator it=b; it!=e; ++it) {
234 237
      indices.push_back(it->first);
235 238
      values.push_back(it->second);
236 239
      collist.push_back(i);
237 240
    }
238 241

	
239 242
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
240 243
                   &indices.front(), &collist.front(), &values.front());
241 244
  }
242 245

	
243 246
  void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
244 247

	
245 248
    int tmp1, tmp2, tmp3, length;
246 249
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
247 250

	
248 251
    length = -length;
249 252
    std::vector<int> indices(length);
250 253
    std::vector<double> values(length);
251 254

	
252 255
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
253 256
               &indices.front(), &values.front(),
254 257
               length, &tmp3, i, i);
255 258

	
256 259
    for (int i = 0; i < length; ++i) {
257 260
      *b = std::make_pair(indices[i], values[i]);
258 261
      ++b;
259 262
    }
260 263

	
261 264
  }
262 265

	
263 266
  void CplexBase::_setCoeff(int row, int col, Value value) {
264 267
    CPXchgcoef(cplexEnv(), _prob, row, col, value);
265 268
  }
266 269

	
267 270
  CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
268 271
    CplexBase::Value value;
269 272
    CPXgetcoef(cplexEnv(), _prob, row, col, &value);
270 273
    return value;
271 274
  }
272 275

	
273 276
  void CplexBase::_setColLowerBound(int i, Value value) {
274 277
    const char s = 'L';
275 278
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
276 279
  }
277 280

	
278 281
  CplexBase::Value CplexBase::_getColLowerBound(int i) const {
279 282
    CplexBase::Value res;
280 283
    CPXgetlb(cplexEnv(), _prob, &res, i, i);
281 284
    return res <= -CPX_INFBOUND ? -INF : res;
282 285
  }
283 286

	
284 287
  void CplexBase::_setColUpperBound(int i, Value value)
285 288
  {
286 289
    const char s = 'U';
287 290
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
288 291
  }
289 292

	
290 293
  CplexBase::Value CplexBase::_getColUpperBound(int i) const {
291 294
    CplexBase::Value res;
292 295
    CPXgetub(cplexEnv(), _prob, &res, i, i);
293 296
    return res >= CPX_INFBOUND ? INF : res;
294 297
  }
295 298

	
296 299
  CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
297 300
    char s;
298 301
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
299 302
    CplexBase::Value res;
300 303

	
301 304
    switch (s) {
302 305
    case 'G':
303 306
    case 'R':
304 307
    case 'E':
305 308
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
306 309
      return res <= -CPX_INFBOUND ? -INF : res;
307 310
    default:
308 311
      return -INF;
309 312
    }
310 313
  }
311 314

	
312 315
  CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
313 316
    char s;
314 317
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
315 318
    CplexBase::Value res;
316 319

	
317 320
    switch (s) {
318 321
    case 'L':
319 322
    case 'E':
320 323
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
321 324
      return res >= CPX_INFBOUND ? INF : res;
322 325
    case 'R':
323 326
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
324 327
      {
325 328
        double rng;
326 329
        CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
327 330
        res += rng;
328 331
      }
329 332
      return res >= CPX_INFBOUND ? INF : res;
330 333
    default:
331 334
      return INF;
332 335
    }
333 336
  }
334 337

	
335 338
  //This is easier to implement
336 339
  void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
337 340
    if (lb == -INF) {
338 341
      const char s = 'L';
339 342
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
340 343
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
341 344
    } else if (ub == INF) {
342 345
      const char s = 'G';
343 346
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
344 347
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
345 348
    } else if (lb == ub){
346 349
      const char s = 'E';
347 350
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
348 351
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
349 352
    } else {
350 353
      const char s = 'R';
351 354
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
352 355
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
353 356
      double len = ub - lb;
354 357
      CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
355 358
    }
356 359
  }
357 360

	
358 361
  void CplexBase::_setRowLowerBound(int i, Value lb)
359 362
  {
360 363
    LEMON_ASSERT(lb != INF, "Invalid bound");
361 364
    _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
362 365
  }
363 366

	
364 367
  void CplexBase::_setRowUpperBound(int i, Value ub)
365 368
  {
366 369

	
367 370
    LEMON_ASSERT(ub != -INF, "Invalid bound");
368 371
    _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
369 372
  }
370 373

	
371 374
  void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
372 375
  {
373 376
    std::vector<int> indices;
374 377
    std::vector<Value> values;
375 378
    for(ExprIterator it=b; it!=e; ++it) {
376 379
      indices.push_back(it->first);
377 380
      values.push_back(it->second);
378 381
    }
379 382
    CPXchgobj(cplexEnv(), _prob, values.size(),
380 383
              &indices.front(), &values.front());
381 384

	
382 385
  }
383 386

	
384 387
  void CplexBase::_getObjCoeffs(InsertIterator b) const
385 388
  {
386 389
    int num = CPXgetnumcols(cplexEnv(), _prob);
387 390
    std::vector<Value> x(num);
388 391

	
389 392
    CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
390 393
    for (int i = 0; i < num; ++i) {
391 394
      if (x[i] != 0.0) {
392 395
        *b = std::make_pair(i, x[i]);
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

	
803 828
#if CPX_VERSION < 800
804 829
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
805 830
#else
806 831
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
807 832
#endif
808 833
  }
809 834

	
810 835
  CplexMip::CplexMip(const CplexEnv& env)
811 836
    : LpBase(), MipSolver(), CplexBase(env) {
812 837

	
813 838
#if CPX_VERSION < 800
814 839
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
815 840
#else
816 841
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
817 842
#endif
818 843

	
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);
915 941
    return x;
916 942
  }
917 943

	
918 944
  CplexMip::Value CplexMip::_getSolValue() const {
919 945
    Value objval;
920 946
    CPXgetmipobjval(cplexEnv(), _prob, &objval);
921 947
    return objval;
922 948
  }
923 949

	
924 950
} //namespace lemon
925 951

	
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
#ifndef LEMON_CPLEX_H
20 20
#define LEMON_CPLEX_H
21 21

	
22 22
///\file
23 23
///\brief Header of the LEMON-CPLEX lp solver interface.
24 24

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

	
27 27
struct cpxenv;
28 28
struct cpxlp;
29 29

	
30 30
namespace lemon {
31 31

	
32 32
  /// \brief Reference counted wrapper around cpxenv pointer
33 33
  ///
34 34
  /// The cplex uses environment object which is responsible for
35 35
  /// checking the proper license usage. This class provides a simple
36 36
  /// interface for share the environment object between different
37 37
  /// problems.
38 38
  class CplexEnv {
39 39
    friend class CplexBase;
40 40
  private:
41 41
    cpxenv* _env;
42 42
    mutable int* _cnt;
43 43

	
44 44
  public:
45 45

	
46 46
    /// \brief This exception is thrown when the license check is not
47 47
    /// sufficient
48 48
    class LicenseError : public Exception {
49 49
      friend class CplexEnv;
50 50
    private:
51 51

	
52 52
      LicenseError(int status);
53 53
      char _message[510];
54 54

	
55 55
    public:
56 56

	
57 57
      /// The short error message
58 58
      virtual const char* what() const throw() {
59 59
        return _message;
60 60
      }
61 61
    };
62 62

	
63 63
    /// Constructor
64 64
    CplexEnv();
65 65
    /// Shallow copy constructor
66 66
    CplexEnv(const CplexEnv&);
67 67
    /// Shallow assignement
68 68
    CplexEnv& operator=(const CplexEnv&);
69 69
    /// Destructor
70 70
    virtual ~CplexEnv();
71 71

	
72 72
  protected:
73 73

	
74 74
    cpxenv* cplexEnv() { return _env; }
75 75
    const cpxenv* cplexEnv() const { return _env; }
76 76
  };
77 77

	
78 78
  /// \brief Base interface for the CPLEX LP and MIP solver
79 79
  ///
80 80
  /// This class implements the common interface of the CPLEX LP and
81 81
  /// MIP solvers.
82 82
  /// \ingroup lp_group
83 83
  class CplexBase : virtual public LpBase {
84 84
  protected:
85 85

	
86 86
    CplexEnv _env;
87 87
    cpxlp* _prob;
88 88

	
89 89
    CplexBase();
90 90
    CplexBase(const CplexEnv&);
91 91
    CplexBase(const CplexBase &);
92 92
    virtual ~CplexBase();
93 93

	
94 94
    virtual int _addCol();
95 95
    virtual int _addRow();
96 96

	
97 97
    virtual void _eraseCol(int i);
98 98
    virtual void _eraseRow(int i);
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;
203 218

	
204 219
    virtual Value _getPrimalRay(int i) const;
205 220
    virtual Value _getDualRay(int i) const;
206 221

	
207 222
    virtual ProblemType _getPrimalType() const;
208 223
    virtual ProblemType _getDualType() const;
209 224

	
210 225
  public:
211 226

	
212 227
    /// Solve with primal simplex method
213 228
    SolveExitStatus solvePrimal();
214 229

	
215 230
    /// Solve with dual simplex method
216 231
    SolveExitStatus solveDual();
217 232

	
218 233
    /// Solve with barrier method
219 234
    SolveExitStatus solveBarrier();
220 235

	
221 236
  };
222 237

	
223 238
  /// \brief Interface for the CPLEX MIP solver
224 239
  ///
225 240
  /// This class implements an interface for the CPLEX MIP solver.
226 241
  ///\ingroup lp_group
227 242
  class CplexMip : public MipSolver, public CplexBase {
228 243
  public:
229 244
    /// \e
230 245
    CplexMip();
231 246
    /// \e
232 247
    CplexMip(const CplexEnv&);
233 248
    /// \e
234 249
    CplexMip(const CplexMip&);
235 250
    /// \e
236 251
    virtual ~CplexMip();
237 252

	
238 253
    /// \e
239 254
    virtual CplexMip* cloneSolver() const;
240 255
    /// \e
241 256
    virtual CplexMip* newSolver() const;
242 257

	
243 258
  protected:
244 259

	
245 260

	
246 261
    virtual const char* _solverName() const;
247 262

	
248 263
    virtual ColTypes _getColType(int col) const;
249 264
    virtual void _setColType(int col, ColTypes col_type);
250 265

	
251 266
    virtual SolveExitStatus _solve();
252 267
    virtual ProblemType _getType() const;
253 268
    virtual Value _getSol(int i) const;
254 269
    virtual Value _getSolValue() const;
255 270

	
256 271
  };
257 272

	
258 273
} //END OF NAMESPACE LEMON
259 274

	
260 275
#endif //LEMON_CPLEX_H
261 276

	
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()));
90 92

	
91 93
  }
92 94

	
93 95
  int GlpkBase::_colByName(const std::string& name) const {
94 96
    int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
95 97
    return k > 0 ? k : -1;
96 98
  }
97 99

	
98 100
  void GlpkBase::_getRowName(int r, std::string& name) const {
99 101
    const char *str = glp_get_row_name(lp, r);
100 102
    if (str) name = str;
101 103
    else name.clear();
102 104
  }
103 105

	
104 106
  void GlpkBase::_setRowName(int r, const std::string & name) {
105 107
    glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
106 108

	
107 109
  }
108 110

	
109 111
  int GlpkBase::_rowByName(const std::string& name) const {
110 112
    int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
111 113
    return k > 0 ? k : -1;
112 114
  }
113 115

	
114 116
  void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
115 117
    std::vector<int> indexes;
116 118
    std::vector<Value> values;
117 119

	
118 120
    indexes.push_back(0);
119 121
    values.push_back(0);
120 122

	
121 123
    for(ExprIterator it = b; it != e; ++it) {
122 124
      indexes.push_back(it->first);
123 125
      values.push_back(it->second);
124 126
    }
125 127

	
126 128
    glp_set_mat_row(lp, i, values.size() - 1,
127 129
                    &indexes.front(), &values.front());
128 130
  }
129 131

	
130 132
  void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
131 133
    int length = glp_get_mat_row(lp, ix, 0, 0);
132 134

	
133 135
    std::vector<int> indexes(length + 1);
134 136
    std::vector<Value> values(length + 1);
135 137

	
136 138
    glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
137 139

	
138 140
    for (int i = 1; i <= length; ++i) {
139 141
      *b = std::make_pair(indexes[i], values[i]);
140 142
      ++b;
141 143
    }
142 144
  }
143 145

	
144 146
  void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
145 147
                                     ExprIterator e) {
146 148

	
147 149
    std::vector<int> indexes;
148 150
    std::vector<Value> values;
149 151

	
150 152
    indexes.push_back(0);
151 153
    values.push_back(0);
152 154

	
153 155
    for(ExprIterator it = b; it != e; ++it) {
154 156
      indexes.push_back(it->first);
155 157
      values.push_back(it->second);
156 158
    }
157 159

	
158 160
    glp_set_mat_col(lp, ix, values.size() - 1,
159 161
                    &indexes.front(), &values.front());
160 162
  }
161 163

	
162 164
  void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
163 165
    int length = glp_get_mat_col(lp, ix, 0, 0);
164 166

	
165 167
    std::vector<int> indexes(length + 1);
166 168
    std::vector<Value> values(length + 1);
167 169

	
168 170
    glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
169 171

	
170 172
    for (int i = 1; i  <= length; ++i) {
171 173
      *b = std::make_pair(indexes[i], values[i]);
172 174
      ++b;
173 175
    }
174 176
  }
175 177

	
176 178
  void GlpkBase::_setCoeff(int ix, int jx, Value value) {
177 179

	
178 180
    if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
179 181

	
180 182
      int length = glp_get_mat_row(lp, ix, 0, 0);
181 183

	
182 184
      std::vector<int> indexes(length + 2);
183 185
      std::vector<Value> values(length + 2);
184 186

	
185 187
      glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
186 188

	
187 189
      //The following code does not suppose that the elements of the
188 190
      //array indexes are sorted
189 191
      bool found = false;
190 192
      for (int i = 1; i  <= length; ++i) {
191 193
        if (indexes[i] == jx) {
192 194
          found = true;
193 195
          values[i] = value;
194 196
          break;
195 197
        }
196 198
      }
197 199
      if (!found) {
198 200
        ++length;
199 201
        indexes[length] = jx;
200 202
        values[length] = value;
201 203
      }
202 204

	
203 205
      glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
204 206

	
205 207
    } else {
206 208

	
207 209
      int length = glp_get_mat_col(lp, jx, 0, 0);
208 210

	
209 211
      std::vector<int> indexes(length + 2);
210 212
      std::vector<Value> values(length + 2);
211 213

	
212 214
      glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
213 215

	
214 216
      //The following code does not suppose that the elements of the
215 217
      //array indexes are sorted
216 218
      bool found = false;
217 219
      for (int i = 1; i <= length; ++i) {
218 220
        if (indexes[i] == ix) {
219 221
          found = true;
220 222
          values[i] = value;
221 223
          break;
222 224
        }
223 225
      }
224 226
      if (!found) {
225 227
        ++length;
226 228
        indexes[length] = ix;
227 229
        values[length] = value;
228 230
      }
229 231

	
230 232
      glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
231 233
    }
232 234

	
233 235
  }
234 236

	
235 237
  GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
236 238

	
237 239
    int length = glp_get_mat_row(lp, ix, 0, 0);
238 240

	
239 241
    std::vector<int> indexes(length + 1);
240 242
    std::vector<Value> values(length + 1);
241 243

	
242 244
    glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
243 245

	
244 246
    for (int i = 1; i  <= length; ++i) {
245 247
      if (indexes[i] == jx) {
246 248
        return values[i];
247 249
      }
248 250
    }
249 251

	
250 252
    return 0;
251 253
  }
252 254

	
253 255
  void GlpkBase::_setColLowerBound(int i, Value lo) {
254 256
    LEMON_ASSERT(lo != INF, "Invalid bound");
255 257

	
256 258
    int b = glp_get_col_type(lp, i);
257 259
    double up = glp_get_col_ub(lp, i);
258 260
    if (lo == -INF) {
259 261
      switch (b) {
260 262
      case GLP_FR:
261 263
      case GLP_LO:
262 264
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
263 265
        break;
264 266
      case GLP_UP:
265 267
        break;
266 268
      case GLP_DB:
267 269
      case GLP_FX:
268 270
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
269 271
        break;
270 272
      default:
271 273
        break;
272 274
      }
273 275
    } else {
274 276
      switch (b) {
275 277
      case GLP_FR:
276 278
      case GLP_LO:
277 279
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
278 280
        break;
279 281
      case GLP_UP:
280 282
      case GLP_DB:
281 283
      case GLP_FX:
282 284
        if (lo == up)
283 285
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
284 286
        else
285 287
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
286 288
        break;
287 289
      default:
288 290
        break;
289 291
      }
290 292
    }
291 293
  }
292 294

	
293 295
  GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
294 296
    int b = glp_get_col_type(lp, i);
295 297
    switch (b) {
296 298
    case GLP_LO:
297 299
    case GLP_DB:
298 300
    case GLP_FX:
299 301
      return glp_get_col_lb(lp, i);
300 302
    default:
301 303
      return -INF;
302 304
    }
303 305
  }
304 306

	
305 307
  void GlpkBase::_setColUpperBound(int i, Value up) {
306 308
    LEMON_ASSERT(up != -INF, "Invalid bound");
307 309

	
308 310
    int b = glp_get_col_type(lp, i);
309 311
    double lo = glp_get_col_lb(lp, i);
310 312
    if (up == INF) {
311 313
      switch (b) {
312 314
      case GLP_FR:
313 315
      case GLP_LO:
314 316
        break;
315 317
      case GLP_UP:
316 318
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
317 319
        break;
318 320
      case GLP_DB:
319 321
      case GLP_FX:
320 322
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
321 323
        break;
322 324
      default:
323 325
        break;
324 326
      }
325 327
    } else {
326 328
      switch (b) {
327 329
      case GLP_FR:
328 330
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
329 331
        break;
330 332
      case GLP_UP:
331 333
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
332 334
        break;
333 335
      case GLP_LO:
334 336
      case GLP_DB:
335 337
      case GLP_FX:
336 338
        if (lo == up)
337 339
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
338 340
        else
339 341
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
340 342
        break;
341 343
      default:
342 344
        break;
343 345
      }
344 346
    }
345 347

	
346 348
  }
347 349

	
348 350
  GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
349 351
    int b = glp_get_col_type(lp, i);
350 352
      switch (b) {
351 353
      case GLP_UP:
352 354
      case GLP_DB:
353 355
      case GLP_FX:
354 356
        return glp_get_col_ub(lp, i);
355 357
      default:
356 358
        return INF;
357 359
      }
358 360
  }
359 361

	
360 362
  void GlpkBase::_setRowLowerBound(int i, Value lo) {
361 363
    LEMON_ASSERT(lo != INF, "Invalid bound");
362 364

	
363 365
    int b = glp_get_row_type(lp, i);
364 366
    double up = glp_get_row_ub(lp, i);
365 367
    if (lo == -INF) {
366 368
      switch (b) {
367 369
      case GLP_FR:
368 370
      case GLP_LO:
369 371
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
370 372
        break;
371 373
      case GLP_UP:
372 374
        break;
373 375
      case GLP_DB:
374 376
      case GLP_FX:
375 377
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
376 378
        break;
377 379
      default:
378 380
        break;
379 381
      }
380 382
    } else {
381 383
      switch (b) {
382 384
      case GLP_FR:
383 385
      case GLP_LO:
384 386
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
385 387
        break;
386 388
      case GLP_UP:
387 389
      case GLP_DB:
388 390
      case GLP_FX:
389 391
        if (lo == up)
390 392
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
391 393
        else
392 394
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
393 395
        break;
394 396
      default:
395 397
        break;
396 398
      }
397 399
    }
398 400

	
399 401
  }
400 402

	
401 403
  GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
402 404
    int b = glp_get_row_type(lp, i);
403 405
    switch (b) {
404 406
    case GLP_LO:
405 407
    case GLP_DB:
406 408
    case GLP_FX:
407 409
      return glp_get_row_lb(lp, i);
408 410
    default:
409 411
      return -INF;
410 412
    }
411 413
  }
412 414

	
413 415
  void GlpkBase::_setRowUpperBound(int i, Value up) {
414 416
    LEMON_ASSERT(up != -INF, "Invalid bound");
415 417

	
416 418
    int b = glp_get_row_type(lp, i);
417 419
    double lo = glp_get_row_lb(lp, i);
418 420
    if (up == INF) {
419 421
      switch (b) {
420 422
      case GLP_FR:
421 423
      case GLP_LO:
422 424
        break;
423 425
      case GLP_UP:
424 426
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
425 427
        break;
426 428
      case GLP_DB:
427 429
      case GLP_FX:
428 430
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
429 431
        break;
430 432
      default:
431 433
        break;
432 434
      }
433 435
    } else {
434 436
      switch (b) {
435 437
      case GLP_FR:
436 438
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
437 439
        break;
438 440
      case GLP_UP:
439 441
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
440 442
        break;
441 443
      case GLP_LO:
442 444
      case GLP_DB:
443 445
      case GLP_FX:
444 446
        if (lo == up)
445 447
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
446 448
        else
447 449
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
448 450
        break;
449 451
      default:
450 452
        break;
451 453
      }
452 454
    }
453 455
  }
454 456

	
455 457
  GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
456 458
    int b = glp_get_row_type(lp, i);
457 459
    switch (b) {
458 460
    case GLP_UP:
459 461
    case GLP_DB:
460 462
    case GLP_FX:
461 463
      return glp_get_row_ub(lp, i);
462 464
    default:
463 465
      return INF;
464 466
    }
465 467
  }
466 468

	
467 469
  void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
468 470
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
469 471
      glp_set_obj_coef(lp, i, 0.0);
470 472
    }
471 473
    for (ExprIterator it = b; it != e; ++it) {
472 474
      glp_set_obj_coef(lp, it->first, it->second);
473 475
    }
474 476
  }
475 477

	
476 478
  void GlpkBase::_getObjCoeffs(InsertIterator b) const {
477 479
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
478 480
      Value val = glp_get_obj_coef(lp, i);
479 481
      if (val != 0.0) {
480 482
        *b = std::make_pair(i, val);
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");
669 663
      return GlpkLp::VarStatus();
670 664
    }
671 665
  }
672 666

	
673 667
  GlpkLp::VarStatus GlpkLp::_getRowStatus(int i) const {
674 668
    switch (glp_get_row_stat(lp, i)) {
675 669
    case GLP_BS:
676 670
      return BASIC;
677 671
    case GLP_UP:
678 672
      return UPPER;
679 673
    case GLP_LO:
680 674
      return LOWER;
681 675
    case GLP_NF:
682 676
      return FREE;
683 677
    case GLP_NS:
684 678
      return FIXED;
685 679
    default:
686 680
      LEMON_ASSERT(false, "Wrong row status");
687 681
      return GlpkLp::VarStatus();
688 682
    }
689 683
  }
690 684

	
691 685
  GlpkLp::Value GlpkLp::_getPrimalRay(int i) const {
692 686
    if (_primal_ray.empty()) {
693 687
      int row_num = glp_get_num_rows(lp);
694 688
      int col_num = glp_get_num_cols(lp);
695 689

	
696 690
      _primal_ray.resize(col_num + 1, 0.0);
697 691

	
698 692
      int index = glp_get_unbnd_ray(lp);
699 693
      if (index != 0) {
700 694
        // The primal ray is found in primal simplex second phase
701 695
        LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
702 696
                      glp_get_col_stat(lp, index - row_num)) != GLP_BS,
703 697
                     "Wrong primal ray");
704 698

	
705 699
        bool negate = glp_get_obj_dir(lp) == GLP_MAX;
706 700

	
707 701
        if (index > row_num) {
708 702
          _primal_ray[index - row_num] = 1.0;
709 703
          if (glp_get_col_dual(lp, index - row_num) > 0) {
710 704
            negate = !negate;
711 705
          }
712 706
        } else {
713 707
          if (glp_get_row_dual(lp, index) > 0) {
714 708
            negate = !negate;
715 709
          }
716 710
        }
717 711

	
718 712
        std::vector<int> ray_indexes(row_num + 1);
719 713
        std::vector<Value> ray_values(row_num + 1);
720 714
        int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
721 715
                                          &ray_values.front());
722 716

	
723 717
        for (int i = 1; i <= ray_length; ++i) {
724 718
          if (ray_indexes[i] > row_num) {
725 719
            _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
726 720
          }
727 721
        }
728 722

	
729 723
        if (negate) {
730 724
          for (int i = 1; i <= col_num; ++i) {
731 725
            _primal_ray[i] = - _primal_ray[i];
732 726
          }
733 727
        }
734 728
      } else {
735 729
        for (int i = 1; i <= col_num; ++i) {
736 730
          _primal_ray[i] = glp_get_col_prim(lp, i);
737 731
        }
738 732
      }
739 733
    }
740 734
    return _primal_ray[i];
741 735
  }
742 736

	
743 737
  GlpkLp::Value GlpkLp::_getDualRay(int i) const {
744 738
    if (_dual_ray.empty()) {
745 739
      int row_num = glp_get_num_rows(lp);
746 740

	
747 741
      _dual_ray.resize(row_num + 1, 0.0);
748 742

	
749 743
      int index = glp_get_unbnd_ray(lp);
750 744
      if (index != 0) {
751 745
        // The dual ray is found in dual simplex second phase
752 746
        LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
753 747
                      glp_get_col_stat(lp, index - row_num)) == GLP_BS,
754 748

	
755 749
                     "Wrong dual ray");
756 750

	
757 751
        int idx;
758 752
        bool negate = false;
759 753

	
760 754
        if (index > row_num) {
761 755
          idx = glp_get_col_bind(lp, index - row_num);
762 756
          if (glp_get_col_prim(lp, index - row_num) >
763 757
              glp_get_col_ub(lp, index - row_num)) {
764 758
            negate = true;
765 759
          }
766 760
        } else {
767 761
          idx = glp_get_row_bind(lp, index);
768 762
          if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
769 763
            negate = true;
770 764
          }
771 765
        }
772 766

	
773 767
        _dual_ray[idx] = negate ?  - 1.0 : 1.0;
774 768

	
775 769
        glp_btran(lp, &_dual_ray.front());
776 770
      } else {
777 771
        double eps = 1e-7;
778 772
        // The dual ray is found in primal simplex first phase
779 773
        // We assume that the glpk minimizes the slack to get feasible solution
780 774
        for (int i = 1; i <= row_num; ++i) {
781 775
          int index = glp_get_bhead(lp, i);
782 776
          if (index <= row_num) {
783 777
            double res = glp_get_row_prim(lp, index);
784 778
            if (res > glp_get_row_ub(lp, index) + eps) {
785 779
              _dual_ray[i] = -1;
786 780
            } else if (res < glp_get_row_lb(lp, index) - eps) {
787 781
              _dual_ray[i] = 1;
788 782
            } else {
789 783
              _dual_ray[i] = 0;
790 784
            }
791 785
            _dual_ray[i] *= glp_get_rii(lp, index);
792 786
          } else {
793 787
            double res = glp_get_col_prim(lp, index - row_num);
794 788
            if (res > glp_get_col_ub(lp, index - row_num) + eps) {
795 789
              _dual_ray[i] = -1;
796 790
            } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
797 791
              _dual_ray[i] = 1;
798 792
            } else {
799 793
              _dual_ray[i] = 0;
800 794
            }
801 795
            _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
802 796
          }
803 797
        }
804 798

	
805 799
        glp_btran(lp, &_dual_ray.front());
806 800

	
807 801
        for (int i = 1; i <= row_num; ++i) {
808 802
          _dual_ray[i] /= glp_get_rii(lp, i);
809 803
        }
810 804
      }
811 805
    }
812 806
    return _dual_ray[i];
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
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
#ifndef LEMON_GLPK_H
20 20
#define LEMON_GLPK_H
21 21

	
22 22
///\file
23 23
///\brief Header of the LEMON-GLPK lp solver interface.
24 24
///\ingroup lp_group
25 25

	
26 26
#include <lemon/lp_base.h>
27 27

	
28 28
// forward declaration
29 29
#ifndef _GLP_PROB
30 30
#define _GLP_PROB
31 31
typedef struct { double _prob; } glp_prob;
32 32
/* LP/MIP problem object */
33 33
#endif
34 34

	
35 35
namespace lemon {
36 36

	
37 37

	
38 38
  /// \brief Base interface for the GLPK LP and MIP solver
39 39
  ///
40 40
  /// This class implements the common interface of the GLPK LP and MIP solver.
41 41
  /// \ingroup lp_group
42 42
  class GlpkBase : virtual public LpBase {
43 43
  protected:
44 44

	
45 45
    typedef glp_prob LPX;
46 46
    glp_prob* lp;
47 47

	
48 48
    GlpkBase();
49 49
    GlpkBase(const GlpkBase&);
50 50
    virtual ~GlpkBase();
51 51

	
52 52
  protected:
53 53

	
54 54
    virtual int _addCol();
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 100663296 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
#ifndef LEMON_LP_BASE_H
20 20
#define LEMON_LP_BASE_H
21 21

	
22 22
#include<iostream>
23 23
#include<vector>
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
      ///
120 135
      bool operator!=(Col c) const  {return _id != c._id;}
121 136
      /// Artificial ordering operator.
122 137

	
123 138
      /// To allow the use of this object in std::map or similar
124 139
      /// associative container we require this.
125 140
      ///
126 141
      /// \note This operator only have to define some strict ordering of
127 142
      /// the items; this order has nothing to do with the iteration
128 143
      /// ordering of the items.
129 144
      bool operator<(Col c) const  {return _id < c._id;}
130 145
    };
131 146

	
132 147
    ///Iterator for iterate over the columns of an LP problem
133 148

	
134 149
    /// Its usage is quite simple, for example you can count the number
135 150
    /// of columns in an LP \c lp:
136 151
    ///\code
137 152
    /// int count=0;
138 153
    /// for (LpBase::ColIt c(lp); c!=INVALID; ++c) ++count;
139 154
    ///\endcode
140 155
    class ColIt : public Col {
141 156
      const LpBase *_solver;
142 157
    public:
143 158
      /// Default constructor
144 159
      
145 160
      /// \warning The default constructor sets the iterator
146 161
      /// to an undefined value.
147 162
      ColIt() {}
148 163
      /// Sets the iterator to the first Col
149 164
      
150 165
      /// Sets the iterator to the first Col.
151 166
      ///
152 167
      ColIt(const LpBase &solver) : _solver(&solver)
153 168
      {
154 169
        _solver->cols.firstItem(_id);
155 170
      }
156 171
      /// Invalid constructor \& conversion
157 172
      
158 173
      /// Initialize the iterator to be invalid.
159 174
      /// \sa Invalid for more details.
160 175
      ColIt(const Invalid&) : Col(INVALID) {}
161 176
      /// Next column
162 177
      
163 178
      /// Assign the iterator to the next column.
164 179
      ///
165 180
      ColIt &operator++()
166 181
      {
167 182
        _solver->cols.nextItem(_id);
168 183
        return *this;
169 184
      }
170 185
    };
171 186

	
172 187
    /// \brief Returns the ID of the column.
173 188
    static int id(const Col& col) { return col._id; }
174 189
    /// \brief Returns the column with the given ID.
175 190
    ///
176 191
    /// \pre The argument should be a valid column ID in the LP problem.
177 192
    static Col colFromId(int id) { return Col(id); }
178 193

	
179 194
    ///Refer to a row of the LP.
180 195

	
181 196
    ///This type is used to refer to a row of the LP.
182 197
    ///
183 198
    ///Its value remains valid and correct even after the addition or erase of
184 199
    ///other rows.
185 200
    ///
186 201
    ///\note This class is similar to other Item types in LEMON, like
187 202
    ///Node and Arc types in digraph.
188 203
    class Row {
189 204
      friend class LpBase;
190 205
    protected:
191 206
      int _id;
192 207
      explicit Row(int id) : _id(id) {}
193 208
    public:
194 209
      typedef Value ExprValue;
195 210
      typedef True LpRow;
196 211
      /// Default constructor
197 212
      
198 213
      /// \warning The default constructor sets the Row to an
199 214
      /// undefined value.
200 215
      Row() {}
201 216
      /// Invalid constructor \& conversion.
202 217
      
203 218
      /// This constructor initializes the Row to be invalid.
204 219
      /// \sa Invalid for more details.      
205 220
      Row(const Invalid&) : _id(-1) {}
206 221
      /// Equality operator
207 222

	
208 223
      /// Two \ref Row "Row"s are equal if and only if they point to
209 224
      /// the same LP row or both are invalid.
210 225
      bool operator==(Row r) const  {return _id == r._id;}
211 226
      /// Inequality operator
212 227
      
213 228
      /// \sa operator==(Row r)
214 229
      ///
215 230
      bool operator!=(Row r) const  {return _id != r._id;}
216 231
      /// Artificial ordering operator.
217 232

	
218 233
      /// To allow the use of this object in std::map or similar
219 234
      /// associative container we require this.
220 235
      ///
221 236
      /// \note This operator only have to define some strict ordering of
222 237
      /// the items; this order has nothing to do with the iteration
223 238
      /// ordering of the items.
224 239
      bool operator<(Row r) const  {return _id < r._id;}
225 240
    };
226 241

	
227 242
    ///Iterator for iterate over the rows of an LP problem
228 243

	
229 244
    /// Its usage is quite simple, for example you can count the number
230 245
    /// of rows in an LP \c lp:
231 246
    ///\code
232 247
    /// int count=0;
233 248
    /// for (LpBase::RowIt c(lp); c!=INVALID; ++c) ++count;
234 249
    ///\endcode
235 250
    class RowIt : public Row {
236 251
      const LpBase *_solver;
237 252
    public:
238 253
      /// Default constructor
239 254
      
240 255
      /// \warning The default constructor sets the iterator
241 256
      /// to an undefined value.
242 257
      RowIt() {}
243 258
      /// Sets the iterator to the first Row
244 259
      
245 260
      /// Sets the iterator to the first Row.
246 261
      ///
247 262
      RowIt(const LpBase &solver) : _solver(&solver)
248 263
      {
249 264
        _solver->rows.firstItem(_id);
250 265
      }
251 266
      /// Invalid constructor \& conversion
252 267
      
253 268
      /// Initialize the iterator to be invalid.
254 269
      /// \sa Invalid for more details.
255 270
      RowIt(const Invalid&) : Row(INVALID) {}
256 271
      /// Next row
257 272
      
258 273
      /// Assign the iterator to the next row.
259 274
      ///
260 275
      RowIt &operator++()
261 276
      {
262 277
        _solver->rows.nextItem(_id);
263 278
        return *this;
264 279
      }
265 280
    };
266 281

	
267 282
    /// \brief Returns the ID of the row.
268 283
    static int id(const Row& row) { return row._id; }
269 284
    /// \brief Returns the row with the given ID.
270 285
    ///
271 286
    /// \pre The argument should be a valid row ID in the LP problem.
272 287
    static Row rowFromId(int id) { return Row(id); }
273 288

	
274 289
  public:
275 290

	
276 291
    ///Linear expression of variables and a constant component
277 292

	
278 293
    ///This data structure stores a linear expression of the variables
279 294
    ///(\ref Col "Col"s) and also has a constant component.
280 295
    ///
281 296
    ///There are several ways to access and modify the contents of this
282 297
    ///container.
283 298
    ///\code
284 299
    ///e[v]=5;
285 300
    ///e[v]+=12;
286 301
    ///e.erase(v);
287 302
    ///\endcode
288 303
    ///or you can also iterate through its elements.
289 304
    ///\code
290 305
    ///double s=0;
291 306
    ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
292 307
    ///  s+=*i * primal(i);
293 308
    ///\endcode
294 309
    ///(This code computes the primal value of the expression).
295 310
    ///- Numbers (<tt>double</tt>'s)
296 311
    ///and variables (\ref Col "Col"s) directly convert to an
297 312
    ///\ref Expr and the usual linear operations are defined, so
298 313
    ///\code
299 314
    ///v+w
300 315
    ///2*v-3.12*(v-w/2)+2
301 316
    ///v*2.1+(3*v+(v*12+w+6)*3)/2
302 317
    ///\endcode
303 318
    ///are valid expressions.
304 319
    ///The usual assignment operations are also defined.
305 320
    ///\code
306 321
    ///e=v+w;
307 322
    ///e+=2*v-3.12*(v-w/2)+2;
308 323
    ///e*=3.4;
309 324
    ///e/=5;
310 325
    ///\endcode
311 326
    ///- The constant member can be set and read by dereference
312 327
    ///  operator (unary *)
313 328
    ///
314 329
    ///\code
315 330
    ///*e=12;
316 331
    ///double c=*e;
317 332
    ///\endcode
318 333
    ///
319 334
    ///\sa Constr
320 335
    class Expr {
321 336
      friend class LpBase;
322 337
    public:
323 338
      /// The key type of the expression
324 339
      typedef LpBase::Col Key;
325 340
      /// The value type of the expression
326 341
      typedef LpBase::Value Value;
327 342

	
328 343
    protected:
329 344
      Value const_comp;
330 345
      std::map<int, Value> comps;
331 346

	
332 347
    public:
333 348
      typedef True SolverExpr;
334 349
      /// Default constructor
335 350
      
336 351
      /// Construct an empty expression, the coefficients and
337 352
      /// the constant component are initialized to zero.
338 353
      Expr() : const_comp(0) {}
339 354
      /// Construct an expression from a column
340 355

	
341 356
      /// Construct an expression, which has a term with \c c variable
342 357
      /// and 1.0 coefficient.
343 358
      Expr(const Col &c) : const_comp(0) {
344 359
        typedef std::map<int, Value>::value_type pair_type;
345 360
        comps.insert(pair_type(id(c), 1));
346 361
      }
347 362
      /// Construct an expression from a constant
348 363

	
349 364
      /// Construct an expression, which's constant component is \c v.
350 365
      ///
351 366
      Expr(const Value &v) : const_comp(v) {}
352 367
      /// Returns the coefficient of the column
353 368
      Value operator[](const Col& c) const {
354 369
        std::map<int, Value>::const_iterator it=comps.find(id(c));
355 370
        if (it != comps.end()) {
356 371
          return it->second;
357 372
        } else {
358 373
          return 0;
359 374
        }
360 375
      }
361 376
      /// Returns the coefficient of the column
362 377
      Value& operator[](const Col& c) {
363 378
        return comps[id(c)];
364 379
      }
365 380
      /// Sets the coefficient of the column
366 381
      void set(const Col &c, const Value &v) {
367 382
        if (v != 0.0) {
368 383
          typedef std::map<int, Value>::value_type pair_type;
369 384
          comps.insert(pair_type(id(c), v));
370 385
        } else {
371 386
          comps.erase(id(c));
372 387
        }
373 388
      }
374 389
      /// Returns the constant component of the expression
375 390
      Value& operator*() { return const_comp; }
376 391
      /// Returns the constant component of the expression
377 392
      const Value& operator*() const { return const_comp; }
378 393
      /// \brief Removes the coefficients which's absolute value does
379 394
      /// not exceed \c epsilon. It also sets to zero the constant
380 395
      /// component, if it does not exceed epsilon in absolute value.
381 396
      void simplify(Value epsilon = 0.0) {
382 397
        std::map<int, Value>::iterator it=comps.begin();
383 398
        while (it != comps.end()) {
384 399
          std::map<int, Value>::iterator jt=it;
385 400
          ++jt;
386 401
          if (std::fabs((*it).second) <= epsilon) comps.erase(it);
387 402
          it=jt;
388 403
        }
389 404
        if (std::fabs(const_comp) <= epsilon) const_comp = 0;
390 405
      }
391 406

	
392 407
      void simplify(Value epsilon = 0.0) const {
393 408
        const_cast<Expr*>(this)->simplify(epsilon);
394 409
      }
395 410

	
396 411
      ///Sets all coefficients and the constant component to 0.
397 412
      void clear() {
398 413
        comps.clear();
399 414
        const_comp=0;
400 415
      }
401 416

	
402 417
      ///Compound assignment
403 418
      Expr &operator+=(const Expr &e) {
404 419
        for (std::map<int, Value>::const_iterator it=e.comps.begin();
405 420
             it!=e.comps.end(); ++it)
406 421
          comps[it->first]+=it->second;
407 422
        const_comp+=e.const_comp;
408 423
        return *this;
409 424
      }
410 425
      ///Compound assignment
411 426
      Expr &operator-=(const Expr &e) {
412 427
        for (std::map<int, Value>::const_iterator it=e.comps.begin();
413 428
             it!=e.comps.end(); ++it)
414 429
          comps[it->first]-=it->second;
415 430
        const_comp-=e.const_comp;
416 431
        return *this;
417 432
      }
418 433
      ///Multiply with a constant
419 434
      Expr &operator*=(const Value &v) {
420 435
        for (std::map<int, Value>::iterator it=comps.begin();
421 436
             it!=comps.end(); ++it)
422 437
          it->second*=v;
423 438
        const_comp*=v;
424 439
        return *this;
425 440
      }
426 441
      ///Division with a constant
427 442
      Expr &operator/=(const Value &c) {
428 443
        for (std::map<int, Value>::iterator it=comps.begin();
429 444
             it!=comps.end(); ++it)
430 445
          it->second/=c;
431 446
        const_comp/=c;
432 447
        return *this;
433 448
      }
434 449

	
435 450
      ///Iterator over the expression
436 451
      
437 452
      ///The iterator iterates over the terms of the expression. 
438 453
      /// 
439 454
      ///\code
440 455
      ///double s=0;
441 456
      ///for(LpBase::Expr::CoeffIt i(e);i!=INVALID;++i)
442 457
      ///  s+= *i * primal(i);
443 458
      ///\endcode
444 459
      class CoeffIt {
445 460
      private:
446 461

	
447 462
        std::map<int, Value>::iterator _it, _end;
448 463

	
449 464
      public:
450 465

	
451 466
        /// Sets the iterator to the first term
452 467
        
453 468
        /// Sets the iterator to the first term of the expression.
454 469
        ///
455 470
        CoeffIt(Expr& e)
456 471
          : _it(e.comps.begin()), _end(e.comps.end()){}
457 472

	
458 473
        /// Convert the iterator to the column of the term
459 474
        operator Col() const {
460 475
          return colFromId(_it->first);
461 476
        }
462 477

	
463 478
        /// Returns the coefficient of the term
464 479
        Value& operator*() { return _it->second; }
465 480

	
466 481
        /// Returns the coefficient of the term
467 482
        const Value& operator*() const { return _it->second; }
468 483
        /// Next term
469 484
        
470 485
        /// Assign the iterator to the next term.
471 486
        ///
472 487
        CoeffIt& operator++() { ++_it; return *this; }
473 488

	
474 489
        /// Equality operator
475 490
        bool operator==(Invalid) const { return _it == _end; }
476 491
        /// Inequality operator
477 492
        bool operator!=(Invalid) const { return _it != _end; }
478 493
      };
479 494

	
480 495
      /// Const iterator over the expression
481 496
      
482 497
      ///The iterator iterates over the terms of the expression. 
483 498
      /// 
484 499
      ///\code
485 500
      ///double s=0;
486 501
      ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
487 502
      ///  s+=*i * primal(i);
488 503
      ///\endcode
489 504
      class ConstCoeffIt {
490 505
      private:
491 506

	
492 507
        std::map<int, Value>::const_iterator _it, _end;
493 508

	
494 509
      public:
495 510

	
496 511
        /// Sets the iterator to the first term
497 512
        
498 513
        /// Sets the iterator to the first term of the expression.
499 514
        ///
500 515
        ConstCoeffIt(const Expr& e)
501 516
          : _it(e.comps.begin()), _end(e.comps.end()){}
502 517

	
503 518
        /// Convert the iterator to the column of the term
504 519
        operator Col() const {
505 520
          return colFromId(_it->first);
506 521
        }
507 522

	
508 523
        /// Returns the coefficient of the term
509 524
        const Value& operator*() const { return _it->second; }
510 525

	
511 526
        /// Next term
512 527
        
513 528
        /// Assign the iterator to the next term.
514 529
        ///
515 530
        ConstCoeffIt& operator++() { ++_it; return *this; }
516 531

	
517 532
        /// Equality operator
518 533
        bool operator==(Invalid) const { return _it == _end; }
519 534
        /// Inequality operator
520 535
        bool operator!=(Invalid) const { return _it != _end; }
521 536
      };
522 537

	
523 538
    };
524 539

	
525 540
    ///Linear constraint
526 541

	
527 542
    ///This data stucture represents a linear constraint in the LP.
528 543
    ///Basically it is a linear expression with a lower or an upper bound
529 544
    ///(or both). These parts of the constraint can be obtained by the member
530 545
    ///functions \ref expr(), \ref lowerBound() and \ref upperBound(),
531 546
    ///respectively.
532 547
    ///There are two ways to construct a constraint.
533 548
    ///- You can set the linear expression and the bounds directly
534 549
    ///  by the functions above.
535 550
    ///- The operators <tt>\<=</tt>, <tt>==</tt> and  <tt>\>=</tt>
536 551
    ///  are defined between expressions, or even between constraints whenever
537 552
    ///  it makes sense. Therefore if \c e and \c f are linear expressions and
538 553
    ///  \c s and \c t are numbers, then the followings are valid expressions
539 554
    ///  and thus they can be used directly e.g. in \ref addRow() whenever
540 555
    ///  it makes sense.
541 556
    ///\code
542 557
    ///  e<=s
543 558
    ///  e<=f
544 559
    ///  e==f
545 560
    ///  s<=e<=t
546 561
    ///  e>=t
547 562
    ///\endcode
548 563
    ///\warning The validity of a constraint is checked only at run
549 564
    ///time, so e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will
550 565
    ///compile, but will fail an assertion.
551 566
    class Constr
552 567
    {
553 568
    public:
554 569
      typedef LpBase::Expr Expr;
555 570
      typedef Expr::Key Key;
556 571
      typedef Expr::Value Value;
557 572

	
558 573
    protected:
559 574
      Expr _expr;
560 575
      Value _lb,_ub;
561 576
    public:
562 577
      ///\e
563 578
      Constr() : _expr(), _lb(NaN), _ub(NaN) {}
564 579
      ///\e
565 580
      Constr(Value lb, const Expr &e, Value ub) :
566 581
        _expr(e), _lb(lb), _ub(ub) {}
567 582
      Constr(const Expr &e) :
568 583
        _expr(e), _lb(NaN), _ub(NaN) {}
569 584
      ///\e
570 585
      void clear()
571 586
      {
572 587
        _expr.clear();
573 588
        _lb=_ub=NaN;
574 589
      }
575 590

	
576 591
      ///Reference to the linear expression
577 592
      Expr &expr() { return _expr; }
578 593
      ///Cont reference to the linear expression
579 594
      const Expr &expr() const { return _expr; }
580 595
      ///Reference to the lower bound.
581 596

	
582 597
      ///\return
583 598
      ///- \ref INF "INF": the constraint is lower unbounded.
584 599
      ///- \ref NaN "NaN": lower bound has not been set.
585 600
      ///- finite number: the lower bound
586 601
      Value &lowerBound() { return _lb; }
587 602
      ///The const version of \ref lowerBound()
588 603
      const Value &lowerBound() const { return _lb; }
589 604
      ///Reference to the upper bound.
590 605

	
591 606
      ///\return
592 607
      ///- \ref INF "INF": the constraint is upper unbounded.
593 608
      ///- \ref NaN "NaN": upper bound has not been set.
594 609
      ///- finite number: the upper bound
595 610
      Value &upperBound() { return _ub; }
596 611
      ///The const version of \ref upperBound()
597 612
      const Value &upperBound() const { return _ub; }
598 613
      ///Is the constraint lower bounded?
599 614
      bool lowerBounded() const {
600 615
        return _lb != -INF && !isNaN(_lb);
601 616
      }
602 617
      ///Is the constraint upper bounded?
603 618
      bool upperBounded() const {
604 619
        return _ub != INF && !isNaN(_ub);
605 620
      }
606 621

	
607 622
    };
608 623

	
609 624
    ///Linear expression of rows
610 625

	
611 626
    ///This data structure represents a column of the matrix,
612 627
    ///thas is it strores a linear expression of the dual variables
613 628
    ///(\ref Row "Row"s).
614 629
    ///
615 630
    ///There are several ways to access and modify the contents of this
616 631
    ///container.
617 632
    ///\code
618 633
    ///e[v]=5;
619 634
    ///e[v]+=12;
620 635
    ///e.erase(v);
621 636
    ///\endcode
622 637
    ///or you can also iterate through its elements.
623 638
    ///\code
624 639
    ///double s=0;
625 640
    ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
626 641
    ///  s+=*i;
627 642
    ///\endcode
628 643
    ///(This code computes the sum of all coefficients).
629 644
    ///- Numbers (<tt>double</tt>'s)
630 645
    ///and variables (\ref Row "Row"s) directly convert to an
631 646
    ///\ref DualExpr and the usual linear operations are defined, so
632 647
    ///\code
633 648
    ///v+w
634 649
    ///2*v-3.12*(v-w/2)
635 650
    ///v*2.1+(3*v+(v*12+w)*3)/2
636 651
    ///\endcode
637 652
    ///are valid \ref DualExpr dual expressions.
638 653
    ///The usual assignment operations are also defined.
639 654
    ///\code
640 655
    ///e=v+w;
641 656
    ///e+=2*v-3.12*(v-w/2);
642 657
    ///e*=3.4;
643 658
    ///e/=5;
644 659
    ///\endcode
645 660
    ///
646 661
    ///\sa Expr
647 662
    class DualExpr {
648 663
      friend class LpBase;
649 664
    public:
650 665
      /// The key type of the expression
651 666
      typedef LpBase::Row Key;
652 667
      /// The value type of the expression
653 668
      typedef LpBase::Value Value;
654 669

	
655 670
    protected:
656 671
      std::map<int, Value> comps;
657 672

	
658 673
    public:
659 674
      typedef True SolverExpr;
660 675
      /// Default constructor
661 676
      
662 677
      /// Construct an empty expression, the coefficients are
663 678
      /// initialized to zero.
664 679
      DualExpr() {}
665 680
      /// Construct an expression from a row
666 681

	
667 682
      /// Construct an expression, which has a term with \c r dual
668 683
      /// variable and 1.0 coefficient.
669 684
      DualExpr(const Row &r) {
670 685
        typedef std::map<int, Value>::value_type pair_type;
671 686
        comps.insert(pair_type(id(r), 1));
672 687
      }
673 688
      /// Returns the coefficient of the row
674 689
      Value operator[](const Row& r) const {
675 690
        std::map<int, Value>::const_iterator it = comps.find(id(r));
676 691
        if (it != comps.end()) {
677 692
          return it->second;
678 693
        } else {
679 694
          return 0;
680 695
        }
681 696
      }
682 697
      /// Returns the coefficient of the row
683 698
      Value& operator[](const Row& r) {
684 699
        return comps[id(r)];
685 700
      }
686 701
      /// Sets the coefficient of the row
687 702
      void set(const Row &r, const Value &v) {
688 703
        if (v != 0.0) {
689 704
          typedef std::map<int, Value>::value_type pair_type;
690 705
          comps.insert(pair_type(id(r), v));
691 706
        } else {
692 707
          comps.erase(id(r));
693 708
        }
694 709
      }
695 710
      /// \brief Removes the coefficients which's absolute value does
696 711
      /// not exceed \c epsilon. 
697 712
      void simplify(Value epsilon = 0.0) {
698 713
        std::map<int, Value>::iterator it=comps.begin();
699 714
        while (it != comps.end()) {
700 715
          std::map<int, Value>::iterator jt=it;
701 716
          ++jt;
702 717
          if (std::fabs((*it).second) <= epsilon) comps.erase(it);
703 718
          it=jt;
704 719
        }
705 720
      }
706 721

	
707 722
      void simplify(Value epsilon = 0.0) const {
708 723
        const_cast<DualExpr*>(this)->simplify(epsilon);
709 724
      }
710 725

	
711 726
      ///Sets all coefficients to 0.
712 727
      void clear() {
713 728
        comps.clear();
714 729
      }
715 730
      ///Compound assignment
716 731
      DualExpr &operator+=(const DualExpr &e) {
717 732
        for (std::map<int, Value>::const_iterator it=e.comps.begin();
718 733
             it!=e.comps.end(); ++it)
719 734
          comps[it->first]+=it->second;
720 735
        return *this;
721 736
      }
722 737
      ///Compound assignment
723 738
      DualExpr &operator-=(const DualExpr &e) {
724 739
        for (std::map<int, Value>::const_iterator it=e.comps.begin();
725 740
             it!=e.comps.end(); ++it)
726 741
          comps[it->first]-=it->second;
727 742
        return *this;
728 743
      }
729 744
      ///Multiply with a constant
730 745
      DualExpr &operator*=(const Value &v) {
731 746
        for (std::map<int, Value>::iterator it=comps.begin();
732 747
             it!=comps.end(); ++it)
733 748
          it->second*=v;
734 749
        return *this;
735 750
      }
736 751
      ///Division with a constant
737 752
      DualExpr &operator/=(const Value &v) {
738 753
        for (std::map<int, Value>::iterator it=comps.begin();
739 754
             it!=comps.end(); ++it)
740 755
          it->second/=v;
741 756
        return *this;
742 757
      }
743 758

	
744 759
      ///Iterator over the expression
745 760
      
746 761
      ///The iterator iterates over the terms of the expression. 
747 762
      /// 
748 763
      ///\code
749 764
      ///double s=0;
750 765
      ///for(LpBase::DualExpr::CoeffIt i(e);i!=INVALID;++i)
751 766
      ///  s+= *i * dual(i);
752 767
      ///\endcode
753 768
      class CoeffIt {
754 769
      private:
755 770

	
756 771
        std::map<int, Value>::iterator _it, _end;
757 772

	
758 773
      public:
759 774

	
760 775
        /// Sets the iterator to the first term
761 776
        
762 777
        /// Sets the iterator to the first term of the expression.
763 778
        ///
764 779
        CoeffIt(DualExpr& e)
765 780
          : _it(e.comps.begin()), _end(e.comps.end()){}
766 781

	
767 782
        /// Convert the iterator to the row of the term
768 783
        operator Row() const {
769 784
          return rowFromId(_it->first);
770 785
        }
771 786

	
772 787
        /// Returns the coefficient of the term
773 788
        Value& operator*() { return _it->second; }
774 789

	
775 790
        /// Returns the coefficient of the term
776 791
        const Value& operator*() const { return _it->second; }
777 792

	
778 793
        /// Next term
779 794
        
780 795
        /// Assign the iterator to the next term.
781 796
        ///
782 797
        CoeffIt& operator++() { ++_it; return *this; }
783 798

	
784 799
        /// Equality operator
785 800
        bool operator==(Invalid) const { return _it == _end; }
786 801
        /// Inequality operator
787 802
        bool operator!=(Invalid) const { return _it != _end; }
788 803
      };
789 804

	
790 805
      ///Iterator over the expression
791 806
      
792 807
      ///The iterator iterates over the terms of the expression. 
793 808
      /// 
794 809
      ///\code
795 810
      ///double s=0;
796 811
      ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
797 812
      ///  s+= *i * dual(i);
798 813
      ///\endcode
799 814
      class ConstCoeffIt {
800 815
      private:
801 816

	
802 817
        std::map<int, Value>::const_iterator _it, _end;
803 818

	
804 819
      public:
805 820

	
806 821
        /// Sets the iterator to the first term
807 822
        
808 823
        /// Sets the iterator to the first term of the expression.
809 824
        ///
810 825
        ConstCoeffIt(const DualExpr& e)
811 826
          : _it(e.comps.begin()), _end(e.comps.end()){}
812 827

	
813 828
        /// Convert the iterator to the row of the term
814 829
        operator Row() const {
815 830
          return rowFromId(_it->first);
816 831
        }
817 832

	
818 833
        /// Returns the coefficient of the term
819 834
        const Value& operator*() const { return _it->second; }
820 835

	
821 836
        /// Next term
822 837
        
823 838
        /// Assign the iterator to the next term.
824 839
        ///
825 840
        ConstCoeffIt& operator++() { ++_it; return *this; }
826 841

	
827 842
        /// Equality operator
828 843
        bool operator==(Invalid) const { return _it == _end; }
829 844
        /// Inequality operator
830 845
        bool operator!=(Invalid) const { return _it != _end; }
831 846
      };
832 847
    };
833 848

	
834 849

	
835 850
  protected:
836 851

	
837 852
    class InsertIterator {
838 853
    private:
839 854

	
840 855
      std::map<int, Value>& _host;
841 856
      const _solver_bits::VarIndex& _index;
842 857

	
843 858
    public:
844 859

	
845 860
      typedef std::output_iterator_tag iterator_category;
846 861
      typedef void difference_type;
847 862
      typedef void value_type;
848 863
      typedef void reference;
849 864
      typedef void pointer;
850 865

	
851 866
      InsertIterator(std::map<int, Value>& host,
852 867
                   const _solver_bits::VarIndex& index)
853 868
        : _host(host), _index(index) {}
854 869

	
855 870
      InsertIterator& operator=(const std::pair<int, Value>& value) {
856 871
        typedef std::map<int, Value>::value_type pair_type;
857 872
        _host.insert(pair_type(_index[value.first], value.second));
858 873
        return *this;
859 874
      }
860 875

	
861 876
      InsertIterator& operator*() { return *this; }
862 877
      InsertIterator& operator++() { return *this; }
863 878
      InsertIterator operator++(int) { return *this; }
864 879

	
865 880
    };
866 881

	
867 882
    class ExprIterator {
868 883
    private:
869 884
      std::map<int, Value>::const_iterator _host_it;
870 885
      const _solver_bits::VarIndex& _index;
871 886
    public:
872 887

	
873 888
      typedef std::bidirectional_iterator_tag iterator_category;
874 889
      typedef std::ptrdiff_t difference_type;
875 890
      typedef const std::pair<int, Value> value_type;
876 891
      typedef value_type reference;
877 892

	
878 893
      class pointer {
879 894
      public:
880 895
        pointer(value_type& _value) : value(_value) {}
881 896
        value_type* operator->() { return &value; }
882 897
      private:
883 898
        value_type value;
884 899
      };
885 900

	
886 901
      ExprIterator(const std::map<int, Value>::const_iterator& host_it,
887 902
                   const _solver_bits::VarIndex& index)
888 903
        : _host_it(host_it), _index(index) {}
889 904

	
890 905
      reference operator*() {
891 906
        return std::make_pair(_index(_host_it->first), _host_it->second);
892 907
      }
893 908

	
894 909
      pointer operator->() {
895 910
        return pointer(operator*());
896 911
      }
897 912

	
898 913
      ExprIterator& operator++() { ++_host_it; return *this; }
899 914
      ExprIterator operator++(int) {
900 915
        ExprIterator tmp(*this); ++_host_it; return tmp;
901 916
      }
902 917

	
903 918
      ExprIterator& operator--() { --_host_it; return *this; }
904 919
      ExprIterator operator--(int) {
905 920
        ExprIterator tmp(*this); --_host_it; return tmp;
906 921
      }
907 922

	
908 923
      bool operator==(const ExprIterator& it) const {
909 924
        return _host_it == it._host_it;
910 925
      }
911 926

	
912 927
      bool operator!=(const ExprIterator& it) const {
913 928
        return _host_it != it._host_it;
914 929
      }
915 930

	
916 931
    };
917 932

	
918 933
  protected:
919 934

	
920 935
    //Abstract virtual functions
921 936

	
922 937
    virtual int _addColId(int col) { return cols.addIndex(col); }
923 938
    virtual int _addRowId(int row) { return rows.addIndex(row); }
924 939

	
925 940
    virtual void _eraseColId(int col) { cols.eraseIndex(col); }
926 941
    virtual void _eraseRowId(int row) { rows.eraseIndex(row); }
927 942

	
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
1024 1041
    template<class T>
1025 1042
    typename enable_if<typename T::value_type::LpCol,int>::type
1026 1043
    addColSet(T &t,dummy<0> = 0) {
1027 1044
      int s=0;
1028 1045
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
1029 1046
      return s;
1030 1047
    }
1031 1048
    template<class T>
1032 1049
    typename enable_if<typename T::value_type::second_type::LpCol,
1033 1050
                       int>::type
1034 1051
    addColSet(T &t,dummy<1> = 1) {
1035 1052
      int s=0;
1036 1053
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
1037 1054
        i->second=addCol();
1038 1055
        s++;
1039 1056
      }
1040 1057
      return s;
1041 1058
    }
1042 1059
    template<class T>
1043 1060
    typename enable_if<typename T::MapIt::Value::LpCol,
1044 1061
                       int>::type
1045 1062
    addColSet(T &t,dummy<2> = 2) {
1046 1063
      int s=0;
1047 1064
      for(typename T::MapIt i(t); i!=INVALID; ++i)
1048 1065
        {
1049 1066
          i.set(addCol());
1050 1067
          s++;
1051 1068
        }
1052 1069
      return s;
1053 1070
    }
1054 1071
#endif
1055 1072

	
1056 1073
    ///Set a column (i.e a dual constraint) of the LP
1057 1074

	
1058 1075
    ///\param c is the column to be modified
1059 1076
    ///\param e is a dual linear expression (see \ref DualExpr)
1060 1077
    ///a better one.
1061 1078
    void col(Col c, const DualExpr &e) {
1062 1079
      e.simplify();
1063 1080
      _setColCoeffs(cols(id(c)), ExprIterator(e.comps.begin(), rows),
1064 1081
                    ExprIterator(e.comps.end(), rows));
1065 1082
    }
1066 1083

	
1067 1084
    ///Get a column (i.e a dual constraint) of the LP
1068 1085

	
1069 1086
    ///\param c is the column to get
1070 1087
    ///\return the dual expression associated to the column
1071 1088
    DualExpr col(Col c) const {
1072 1089
      DualExpr e;
1073 1090
      _getColCoeffs(cols(id(c)), InsertIterator(e.comps, rows));
1074 1091
      return e;
1075 1092
    }
1076 1093

	
1077 1094
    ///Add a new column to the LP
1078 1095

	
1079 1096
    ///\param e is a dual linear expression (see \ref DualExpr)
1080 1097
    ///\param o is the corresponding component of the objective
1081 1098
    ///function. It is 0 by default.
1082 1099
    ///\return The created column.
1083 1100
    Col addCol(const DualExpr &e, Value o = 0) {
1084 1101
      Col c=addCol();
1085 1102
      col(c,e);
1086 1103
      objCoeff(c,o);
1087 1104
      return c;
1088 1105
    }
1089 1106

	
1090 1107
    ///Add a new empty row (i.e a new constraint) to the LP
1091 1108

	
1092 1109
    ///This function adds a new empty row (i.e a new constraint) to the LP.
1093 1110
    ///\return The created row
1094 1111
    Row addRow() { Row r; r._id = _addRowId(_addRow()); return r;}
1095 1112

	
1096 1113
    ///\brief Add several new rows (i.e constraints) at once
1097 1114
    ///
1098 1115
    ///This magic function takes a container as its argument and fills
1099 1116
    ///its elements with new row (i.e. variables)
1100 1117
    ///\param t can be
1101 1118
    ///- a standard STL compatible iterable container with
1102 1119
    ///\ref Row as its \c values_type like
1103 1120
    ///\code
1104 1121
    ///std::vector<LpBase::Row>
1105 1122
    ///std::list<LpBase::Row>
1106 1123
    ///\endcode
1107 1124
    ///- a standard STL compatible iterable container with
1108 1125
    ///\ref Row as its \c mapped_type like
1109 1126
    ///\code
1110 1127
    ///std::map<AnyType,LpBase::Row>
1111 1128
    ///\endcode
1112 1129
    ///- an iterable lemon \ref concepts::WriteMap "write map" like
1113 1130
    ///\code
1114 1131
    ///ListGraph::NodeMap<LpBase::Row>
1115 1132
    ///ListGraph::ArcMap<LpBase::Row>
1116 1133
    ///\endcode
1117 1134
    ///\return The number of rows created.
1118 1135
#ifdef DOXYGEN
1119 1136
    template<class T>
1120 1137
    int addRowSet(T &t) { return 0;}
1121 1138
#else
1122 1139
    template<class T>
1123 1140
    typename enable_if<typename T::value_type::LpRow,int>::type
1124 1141
    addRowSet(T &t, dummy<0> = 0) {
1125 1142
      int s=0;
1126 1143
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
1127 1144
      return s;
1128 1145
    }
1129 1146
    template<class T>
1130 1147
    typename enable_if<typename T::value_type::second_type::LpRow, int>::type
1131 1148
    addRowSet(T &t, dummy<1> = 1) {
1132 1149
      int s=0;
1133 1150
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
1134 1151
        i->second=addRow();
1135 1152
        s++;
1136 1153
      }
1137 1154
      return s;
1138 1155
    }
1139 1156
    template<class T>
1140 1157
    typename enable_if<typename T::MapIt::Value::LpRow, int>::type
1141 1158
    addRowSet(T &t, dummy<2> = 2) {
1142 1159
      int s=0;
1143 1160
      for(typename T::MapIt i(t); i!=INVALID; ++i)
1144 1161
        {
1145 1162
          i.set(addRow());
1146 1163
          s++;
1147 1164
        }
1148 1165
      return s;
1149 1166
    }
1150 1167
#endif
1151 1168

	
1152 1169
    ///Set a row (i.e a constraint) of the LP
1153 1170

	
1154 1171
    ///\param r is the row to be modified
1155 1172
    ///\param l is lower bound (-\ref INF means no bound)
1156 1173
    ///\param e is a linear expression (see \ref Expr)
1157 1174
    ///\param u is the upper bound (\ref INF means no bound)
1158 1175
    void row(Row r, Value l, const Expr &e, Value u) {
1159 1176
      e.simplify();
1160 1177
      _setRowCoeffs(rows(id(r)), ExprIterator(e.comps.begin(), cols),
1161 1178
                    ExprIterator(e.comps.end(), cols));
1162 1179
      _setRowLowerBound(rows(id(r)),l - *e);
1163 1180
      _setRowUpperBound(rows(id(r)),u - *e);
1164 1181
    }
1165 1182

	
1166 1183
    ///Set a row (i.e a constraint) of the LP
1167 1184

	
1168 1185
    ///\param r is the row to be modified
1169 1186
    ///\param c is a linear expression (see \ref Constr)
1170 1187
    void row(Row r, const Constr &c) {
1171 1188
      row(r, c.lowerBounded()?c.lowerBound():-INF,
1172 1189
          c.expr(), c.upperBounded()?c.upperBound():INF);
1173 1190
    }
1174 1191

	
1175 1192

	
1176 1193
    ///Get a row (i.e a constraint) of the LP
1177 1194

	
1178 1195
    ///\param r is the row to get
1179 1196
    ///\return the expression associated to the row
1180 1197
    Expr row(Row r) const {
1181 1198
      Expr e;
1182 1199
      _getRowCoeffs(rows(id(r)), InsertIterator(e.comps, cols));
1183 1200
      return e;
1184 1201
    }
1185 1202

	
1186 1203
    ///Add a new row (i.e a new constraint) to the LP
1187 1204

	
1188 1205
    ///\param l is the lower bound (-\ref INF means no bound)
1189 1206
    ///\param e is a linear expression (see \ref Expr)
1190 1207
    ///\param u is the upper bound (\ref INF means no bound)
1191 1208
    ///\return The created row.
1192 1209
    Row addRow(Value l,const Expr &e, Value u) {
1193 1210
      Row r=addRow();
1194 1211
      row(r,l,e,u);
1195 1212
      return r;
1196 1213
    }
1197 1214

	
1198 1215
    ///Add a new row (i.e a new constraint) to the LP
1199 1216

	
1200 1217
    ///\param c is a linear expression (see \ref Constr)
1201 1218
    ///\return The created row.
1202 1219
    Row addRow(const Constr &c) {
1203 1220
      Row r=addRow();
1204 1221
      row(r,c);
1205 1222
      return r;
1206 1223
    }
1207 1224
    ///Erase a column (i.e a variable) from the LP
1208 1225

	
1209 1226
    ///\param c is the column to be deleted
1210 1227
    void erase(Col c) {
1211 1228
      _eraseCol(cols(id(c)));
1212 1229
      _eraseColId(cols(id(c)));
1213 1230
    }
1214 1231
    ///Erase a row (i.e a constraint) from the LP
1215 1232

	
1216 1233
    ///\param r is the row to be deleted
1217 1234
    void erase(Row r) {
1218 1235
      _eraseRow(rows(id(r)));
1219 1236
      _eraseRowId(rows(id(r)));
1220 1237
    }
1221 1238

	
1222 1239
    /// Get the name of a column
1223 1240

	
1224 1241
    ///\param c is the coresponding column
1225 1242
    ///\return The name of the colunm
1226 1243
    std::string colName(Col c) const {
1227 1244
      std::string name;
1228 1245
      _getColName(cols(id(c)), name);
1229 1246
      return name;
1230 1247
    }
1231 1248

	
1232 1249
    /// Set the name of a column
1233 1250

	
1234 1251
    ///\param c is the coresponding column
1235 1252
    ///\param name The name to be given
1236 1253
    void colName(Col c, const std::string& name) {
1237 1254
      _setColName(cols(id(c)), name);
1238 1255
    }
1239 1256

	
1240 1257
    /// Get the column by its name
1241 1258

	
1242 1259
    ///\param name The name of the column
1243 1260
    ///\return the proper column or \c INVALID
1244 1261
    Col colByName(const std::string& name) const {
1245 1262
      int k = _colByName(name);
1246 1263
      return k != -1 ? Col(cols[k]) : Col(INVALID);
1247 1264
    }
1248 1265

	
1249 1266
    /// Get the name of a row
1250 1267

	
1251 1268
    ///\param r is the coresponding row
1252 1269
    ///\return The name of the row
1253 1270
    std::string rowName(Row r) const {
1254 1271
      std::string name;
1255 1272
      _getRowName(rows(id(r)), name);
1256 1273
      return name;
1257 1274
    }
1258 1275

	
1259 1276
    /// Set the name of a row
1260 1277

	
1261 1278
    ///\param r is the coresponding row
1262 1279
    ///\param name The name to be given
1263 1280
    void rowName(Row r, const std::string& name) {
1264 1281
      _setRowName(rows(id(r)), name);
1265 1282
    }
1266 1283

	
1267 1284
    /// Get the row by its name
1268 1285

	
1269 1286
    ///\param name The name of the row
1270 1287
    ///\return the proper row or \c INVALID
1271 1288
    Row rowByName(const std::string& name) const {
1272 1289
      int k = _rowByName(name);
1273 1290
      return k != -1 ? Row(rows[k]) : Row(INVALID);
1274 1291
    }
1275 1292

	
1276 1293
    /// Set an element of the coefficient matrix of the LP
1277 1294

	
1278 1295
    ///\param r is the row of the element to be modified
1279 1296
    ///\param c is the column of the element to be modified
1280 1297
    ///\param val is the new value of the coefficient
1281 1298
    void coeff(Row r, Col c, Value val) {
1282 1299
      _setCoeff(rows(id(r)),cols(id(c)), val);
1283 1300
    }
1284 1301

	
1285 1302
    /// Get an element of the coefficient matrix of the LP
1286 1303

	
1287 1304
    ///\param r is the row of the element
1288 1305
    ///\param c is the column of the element
1289 1306
    ///\return the corresponding coefficient
1290 1307
    Value coeff(Row r, Col c) const {
1291 1308
      return _getCoeff(rows(id(r)),cols(id(c)));
1292 1309
    }
1293 1310

	
1294 1311
    /// Set the lower bound of a column (i.e a variable)
1295 1312

	
1296 1313
    /// The lower bound of a variable (column) has to be given by an
1297 1314
    /// extended number of type Value, i.e. a finite number of type
1298 1315
    /// Value or -\ref INF.
1299 1316
    void colLowerBound(Col c, Value value) {
1300 1317
      _setColLowerBound(cols(id(c)),value);
1301 1318
    }
1302 1319

	
1303 1320
    /// Get the lower bound of a column (i.e a variable)
1304 1321

	
1305 1322
    /// This function returns the lower bound for column (variable) \c c
1306 1323
    /// (this might be -\ref INF as well).
1307 1324
    ///\return The lower bound for column \c c
1308 1325
    Value colLowerBound(Col c) const {
1309 1326
      return _getColLowerBound(cols(id(c)));
1310 1327
    }
1311 1328

	
1312 1329
    ///\brief Set the lower bound of  several columns
1313 1330
    ///(i.e variables) at once
1314 1331
    ///
1315 1332
    ///This magic function takes a container as its argument
1316 1333
    ///and applies the function on all of its elements.
1317 1334
    ///The lower bound of a variable (column) has to be given by an
1318 1335
    ///extended number of type Value, i.e. a finite number of type
1319 1336
    ///Value or -\ref INF.
1320 1337
#ifdef DOXYGEN
1321 1338
    template<class T>
1322 1339
    void colLowerBound(T &t, Value value) { return 0;}
1323 1340
#else
1324 1341
    template<class T>
1325 1342
    typename enable_if<typename T::value_type::LpCol,void>::type
1326 1343
    colLowerBound(T &t, Value value,dummy<0> = 0) {
1327 1344
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
1328 1345
        colLowerBound(*i, value);
1329 1346
      }
1330 1347
    }
1331 1348
    template<class T>
1332 1349
    typename enable_if<typename T::value_type::second_type::LpCol,
1333 1350
                       void>::type
1334 1351
    colLowerBound(T &t, Value value,dummy<1> = 1) {
1335 1352
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
1336 1353
        colLowerBound(i->second, value);
1337 1354
      }
1338 1355
    }
1339 1356
    template<class T>
1340 1357
    typename enable_if<typename T::MapIt::Value::LpCol,
1341 1358
                       void>::type
1342 1359
    colLowerBound(T &t, Value value,dummy<2> = 2) {
1343 1360
      for(typename T::MapIt i(t); i!=INVALID; ++i){
1344 1361
        colLowerBound(*i, value);
1345 1362
      }
1346 1363
    }
1347 1364
#endif
1348 1365

	
1349 1366
    /// Set the upper bound of a column (i.e a variable)
1350 1367

	
1351 1368
    /// The upper bound of a variable (column) has to be given by an
1352 1369
    /// extended number of type Value, i.e. a finite number of type
1353 1370
    /// Value or \ref INF.
1354 1371
    void colUpperBound(Col c, Value value) {
1355 1372
      _setColUpperBound(cols(id(c)),value);
1356 1373
    };
1357 1374

	
1358 1375
    /// Get the upper bound of a column (i.e a variable)
1359 1376

	
1360 1377
    /// This function returns the upper bound for column (variable) \c c
1361 1378
    /// (this might be \ref INF as well).
1362 1379
    /// \return The upper bound for column \c c
1363 1380
    Value colUpperBound(Col c) const {
1364 1381
      return _getColUpperBound(cols(id(c)));
1365 1382
    }
1366 1383

	
1367 1384
    ///\brief Set the upper bound of  several columns
1368 1385
    ///(i.e variables) at once
1369 1386
    ///
1370 1387
    ///This magic function takes a container as its argument
1371 1388
    ///and applies the function on all of its elements.
1372 1389
    ///The upper bound of a variable (column) has to be given by an
1373 1390
    ///extended number of type Value, i.e. a finite number of type
1374 1391
    ///Value or \ref INF.
1375 1392
#ifdef DOXYGEN
1376 1393
    template<class T>
1377 1394
    void colUpperBound(T &t, Value value) { return 0;}
1378 1395
#else
1379 1396
    template<class T1>
1380 1397
    typename enable_if<typename T1::value_type::LpCol,void>::type
1381 1398
    colUpperBound(T1 &t, Value value,dummy<0> = 0) {
1382 1399
      for(typename T1::iterator i=t.begin();i!=t.end();++i) {
1383 1400
        colUpperBound(*i, value);
1384 1401
      }
1385 1402
    }
1386 1403
    template<class T1>
1387 1404
    typename enable_if<typename T1::value_type::second_type::LpCol,
1388 1405
                       void>::type
1389 1406
    colUpperBound(T1 &t, Value value,dummy<1> = 1) {
1390 1407
      for(typename T1::iterator i=t.begin();i!=t.end();++i) {
1391 1408
        colUpperBound(i->second, value);
1392 1409
      }
1393 1410
    }
1394 1411
    template<class T1>
1395 1412
    typename enable_if<typename T1::MapIt::Value::LpCol,
1396 1413
                       void>::type
1397 1414
    colUpperBound(T1 &t, Value value,dummy<2> = 2) {
1398 1415
      for(typename T1::MapIt i(t); i!=INVALID; ++i){
1399 1416
        colUpperBound(*i, value);
1400 1417
      }
1401 1418
    }
1402 1419
#endif
1403 1420

	
1404 1421
    /// Set the lower and the upper bounds of a column (i.e a variable)
1405 1422

	
1406 1423
    /// The lower and the upper bounds of
1407 1424
    /// a variable (column) have to be given by an
1408 1425
    /// extended number of type Value, i.e. a finite number of type
1409 1426
    /// Value, -\ref INF or \ref INF.
1410 1427
    void colBounds(Col c, Value lower, Value upper) {
1411 1428
      _setColLowerBound(cols(id(c)),lower);
1412 1429
      _setColUpperBound(cols(id(c)),upper);
1413 1430
    }
1414 1431

	
1415 1432
    ///\brief Set the lower and the upper bound of several columns
1416 1433
    ///(i.e variables) at once
1417 1434
    ///
1418 1435
    ///This magic function takes a container as its argument
1419 1436
    ///and applies the function on all of its elements.
1420 1437
    /// The lower and the upper bounds of
1421 1438
    /// a variable (column) have to be given by an
1422 1439
    /// extended number of type Value, i.e. a finite number of type
1423 1440
    /// Value, -\ref INF or \ref INF.
1424 1441
#ifdef DOXYGEN
1425 1442
    template<class T>
1426 1443
    void colBounds(T &t, Value lower, Value upper) { return 0;}
1427 1444
#else
1428 1445
    template<class T2>
1429 1446
    typename enable_if<typename T2::value_type::LpCol,void>::type
1430 1447
    colBounds(T2 &t, Value lower, Value upper,dummy<0> = 0) {
1431 1448
      for(typename T2::iterator i=t.begin();i!=t.end();++i) {
1432 1449
        colBounds(*i, lower, upper);
1433 1450
      }
1434 1451
    }
1435 1452
    template<class T2>
1436 1453
    typename enable_if<typename T2::value_type::second_type::LpCol, void>::type
1437 1454
    colBounds(T2 &t, Value lower, Value upper,dummy<1> = 1) {
1438 1455
      for(typename T2::iterator i=t.begin();i!=t.end();++i) {
1439 1456
        colBounds(i->second, lower, upper);
1440 1457
      }
1441 1458
    }
1442 1459
    template<class T2>
1443 1460
    typename enable_if<typename T2::MapIt::Value::LpCol, void>::type
1444 1461
    colBounds(T2 &t, Value lower, Value upper,dummy<2> = 2) {
1445 1462
      for(typename T2::MapIt i(t); i!=INVALID; ++i){
1446 1463
        colBounds(*i, lower, upper);
1447 1464
      }
1448 1465
    }
1449 1466
#endif
1450 1467

	
1451 1468
    /// Set the lower bound of a row (i.e a constraint)
1452 1469

	
1453 1470
    /// The lower bound of a constraint (row) has to be given by an
1454 1471
    /// extended number of type Value, i.e. a finite number of type
1455 1472
    /// Value or -\ref INF.
1456 1473
    void rowLowerBound(Row r, Value value) {
1457 1474
      _setRowLowerBound(rows(id(r)),value);
1458 1475
    }
1459 1476

	
1460 1477
    /// Get the lower bound of a row (i.e a constraint)
1461 1478

	
1462 1479
    /// This function returns the lower bound for row (constraint) \c c
1463 1480
    /// (this might be -\ref INF as well).
1464 1481
    ///\return The lower bound for row \c r
1465 1482
    Value rowLowerBound(Row r) const {
1466 1483
      return _getRowLowerBound(rows(id(r)));
1467 1484
    }
1468 1485

	
1469 1486
    /// Set the upper bound of a row (i.e a constraint)
1470 1487

	
1471 1488
    /// The upper bound of a constraint (row) has to be given by an
1472 1489
    /// extended number of type Value, i.e. a finite number of type
1473 1490
    /// Value or -\ref INF.
1474 1491
    void rowUpperBound(Row r, Value value) {
1475 1492
      _setRowUpperBound(rows(id(r)),value);
1476 1493
    }
1477 1494

	
1478 1495
    /// Get the upper bound of a row (i.e a constraint)
1479 1496

	
1480 1497
    /// This function returns the upper bound for row (constraint) \c c
1481 1498
    /// (this might be -\ref INF as well).
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;
1578 1598
    return tmp;
1579 1599
  }
1580 1600

	
1581 1601
  ///Create constraint
1582 1602

	
1583 1603
  ///\relates LpBase::Constr
1584 1604
  ///
1585 1605
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1586 1606
                                   const LpBase::Expr &f) {
1587 1607
    return LpBase::Constr(0, f - e, LpBase::INF);
1588 1608
  }
1589 1609

	
1590 1610
  ///Create constraint
1591 1611

	
1592 1612
  ///\relates LpBase::Constr
1593 1613
  ///
1594 1614
  inline LpBase::Constr operator<=(const LpBase::Value &e,
1595 1615
                                   const LpBase::Expr &f) {
1596 1616
    return LpBase::Constr(e, f, LpBase::NaN);
1597 1617
  }
1598 1618

	
1599 1619
  ///Create constraint
1600 1620

	
1601 1621
  ///\relates LpBase::Constr
1602 1622
  ///
1603 1623
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1604 1624
                                   const LpBase::Value &f) {
1605 1625
    return LpBase::Constr(- LpBase::INF, e, f);
1606 1626
  }
1607 1627

	
1608 1628
  ///Create constraint
1609 1629

	
1610 1630
  ///\relates LpBase::Constr
1611 1631
  ///
1612 1632
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1613 1633
                                   const LpBase::Expr &f) {
1614 1634
    return LpBase::Constr(0, e - f, LpBase::INF);
1615 1635
  }
1616 1636

	
1617 1637

	
1618 1638
  ///Create constraint
1619 1639

	
1620 1640
  ///\relates LpBase::Constr
1621 1641
  ///
1622 1642
  inline LpBase::Constr operator>=(const LpBase::Value &e,
1623 1643
                                   const LpBase::Expr &f) {
1624 1644
    return LpBase::Constr(LpBase::NaN, f, e);
1625 1645
  }
1626 1646

	
1627 1647

	
1628 1648
  ///Create constraint
1629 1649

	
1630 1650
  ///\relates LpBase::Constr
1631 1651
  ///
1632 1652
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1633 1653
                                   const LpBase::Value &f) {
1634 1654
    return LpBase::Constr(f, e, LpBase::INF);
1635 1655
  }
1636 1656

	
1637 1657
  ///Create constraint
1638 1658

	
1639 1659
  ///\relates LpBase::Constr
1640 1660
  ///
1641 1661
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1642 1662
                                   const LpBase::Value &f) {
1643 1663
    return LpBase::Constr(f, e, f);
1644 1664
  }
1645 1665

	
1646 1666
  ///Create constraint
1647 1667

	
1648 1668
  ///\relates LpBase::Constr
1649 1669
  ///
1650 1670
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1651 1671
                                   const LpBase::Expr &f) {
1652 1672
    return LpBase::Constr(0, f - e, 0);
1653 1673
  }
1654 1674

	
1655 1675
  ///Create constraint
1656 1676

	
1657 1677
  ///\relates LpBase::Constr
1658 1678
  ///
1659 1679
  inline LpBase::Constr operator<=(const LpBase::Value &n,
1660 1680
                                   const LpBase::Constr &c) {
1661 1681
    LpBase::Constr tmp(c);
1662 1682
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1663 1683
    tmp.lowerBound()=n;
1664 1684
    return tmp;
1665 1685
  }
1666 1686
  ///Create constraint
1667 1687

	
1668 1688
  ///\relates LpBase::Constr
1669 1689
  ///
1670 1690
  inline LpBase::Constr operator<=(const LpBase::Constr &c,
1671 1691
                                   const LpBase::Value &n)
1672 1692
  {
1673 1693
    LpBase::Constr tmp(c);
1674 1694
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1675 1695
    tmp.upperBound()=n;
1676 1696
    return tmp;
1677 1697
  }
1678 1698

	
1679 1699
  ///Create constraint
1680 1700

	
1681 1701
  ///\relates LpBase::Constr
1682 1702
  ///
1683 1703
  inline LpBase::Constr operator>=(const LpBase::Value &n,
1684 1704
                                   const LpBase::Constr &c) {
1685 1705
    LpBase::Constr tmp(c);
1686 1706
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1687 1707
    tmp.upperBound()=n;
1688 1708
    return tmp;
1689 1709
  }
1690 1710
  ///Create constraint
1691 1711

	
1692 1712
  ///\relates LpBase::Constr
1693 1713
  ///
1694 1714
  inline LpBase::Constr operator>=(const LpBase::Constr &c,
1695 1715
                                   const LpBase::Value &n)
1696 1716
  {
1697 1717
    LpBase::Constr tmp(c);
1698 1718
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1699 1719
    tmp.lowerBound()=n;
1700 1720
    return tmp;
1701 1721
  }
1702 1722

	
1703 1723
  ///Addition
1704 1724

	
1705 1725
  ///\relates LpBase::DualExpr
1706 1726
  ///
1707 1727
  inline LpBase::DualExpr operator+(const LpBase::DualExpr &a,
1708 1728
                                    const LpBase::DualExpr &b) {
1709 1729
    LpBase::DualExpr tmp(a);
1710 1730
    tmp+=b;
1711 1731
    return tmp;
1712 1732
  }
1713 1733
  ///Substraction
1714 1734

	
1715 1735
  ///\relates LpBase::DualExpr
1716 1736
  ///
1717 1737
  inline LpBase::DualExpr operator-(const LpBase::DualExpr &a,
1718 1738
                                    const LpBase::DualExpr &b) {
1719 1739
    LpBase::DualExpr tmp(a);
1720 1740
    tmp-=b;
1721 1741
    return tmp;
1722 1742
  }
1723 1743
  ///Multiply with constant
1724 1744

	
1725 1745
  ///\relates LpBase::DualExpr
1726 1746
  ///
1727 1747
  inline LpBase::DualExpr operator*(const LpBase::DualExpr &a,
1728 1748
                                    const LpBase::Value &b) {
1729 1749
    LpBase::DualExpr tmp(a);
1730 1750
    tmp*=b;
1731 1751
    return tmp;
1732 1752
  }
1733 1753

	
1734 1754
  ///Multiply with constant
1735 1755

	
1736 1756
  ///\relates LpBase::DualExpr
1737 1757
  ///
1738 1758
  inline LpBase::DualExpr operator*(const LpBase::Value &a,
1739 1759
                                    const LpBase::DualExpr &b) {
1740 1760
    LpBase::DualExpr tmp(b);
1741 1761
    tmp*=a;
1742 1762
    return tmp;
1743 1763
  }
1744 1764
  ///Divide with constant
1745 1765

	
1746 1766
  ///\relates LpBase::DualExpr
1747 1767
  ///
1748 1768
  inline LpBase::DualExpr operator/(const LpBase::DualExpr &a,
1749 1769
                                    const LpBase::Value &b) {
1750 1770
    LpBase::DualExpr tmp(a);
1751 1771
    tmp/=b;
1752 1772
    return tmp;
1753 1773
  }
1754 1774

	
1755 1775
  /// \ingroup lp_group
1756 1776
  ///
1757 1777
  /// \brief Common base class for LP solvers
1758 1778
  ///
1759 1779
  /// This class is an abstract base class for LP solvers. This class
1760 1780
  /// provides a full interface for set and modify an LP problem,
1761 1781
  /// solve it and retrieve the solution. You can use one of the
1762 1782
  /// descendants as a concrete implementation, or the \c Lp
1763 1783
  /// default LP solver. However, if you would like to handle LP
1764 1784
  /// solvers as reference or pointer in a generic way, you can use
1765 1785
  /// this class directly.
1766 1786
  class LpSolver : virtual public LpBase {
1767 1787
  public:
1768 1788

	
1769 1789
    /// The problem types for primal and dual problems
1770 1790
    enum ProblemType {
1771 1791
      ///Feasible solution hasn't been found (but may exist).
1772 1792
      UNDEFINED = 0,
1773 1793
      ///The problem has no feasible solution
1774 1794
      INFEASIBLE = 1,
1775 1795
      ///Feasible solution found
1776 1796
      FEASIBLE = 2,
1777 1797
      ///Optimal solution exists and found
1778 1798
      OPTIMAL = 3,
1779 1799
      ///The cost function is unbounded
1780 1800
      UNBOUNDED = 4
1781 1801
    };
1782 1802

	
1783 1803
    ///The basis status of variables
1784 1804
    enum VarStatus {
1785 1805
      /// The variable is in the basis
1786 1806
      BASIC, 
1787 1807
      /// The variable is free, but not basic
1788 1808
      FREE,
1789 1809
      /// The variable has active lower bound 
1790 1810
      LOWER,
1791 1811
      /// The variable has active upper bound
1792 1812
      UPPER,
1793 1813
      /// The variable is non-basic and fixed
1794 1814
      FIXED
1795 1815
    };
1796 1816

	
1797 1817
  protected:
1798 1818

	
1799 1819
    virtual SolveExitStatus _solve() = 0;
1800 1820

	
1801 1821
    virtual Value _getPrimal(int i) const = 0;
1802 1822
    virtual Value _getDual(int i) const = 0;
1803 1823

	
1804 1824
    virtual Value _getPrimalRay(int i) const = 0;
1805 1825
    virtual Value _getDualRay(int i) const = 0;
1806 1826

	
1807 1827
    virtual Value _getPrimalValue() const = 0;
1808 1828

	
1809 1829
    virtual VarStatus _getColStatus(int i) const = 0;
1810 1830
    virtual VarStatus _getRowStatus(int i) const = 0;
1811 1831

	
1812 1832
    virtual ProblemType _getPrimalType() const = 0;
1813 1833
    virtual ProblemType _getDualType() const = 0;
1814 1834

	
1815 1835
  public:
1816 1836

	
1817 1837
    ///Allocate a new LP problem instance
1818 1838
    virtual LpSolver* newSolver() const = 0;
1819 1839
    ///Make a copy of the LP problem
1820 1840
    virtual LpSolver* cloneSolver() const = 0;
1821 1841

	
1822 1842
    ///\name Solve the LP
1823 1843

	
1824 1844
    ///@{
1825 1845

	
1826 1846
    ///\e Solve the LP problem at hand
1827 1847
    ///
1828 1848
    ///\return The result of the optimization procedure. Possible
1829 1849
    ///values and their meanings can be found in the documentation of
1830 1850
    ///\ref SolveExitStatus.
1831 1851
    SolveExitStatus solve() { return _solve(); }
1832 1852

	
1833 1853
    ///@}
1834 1854

	
1835 1855
    ///\name Obtain the solution
1836 1856

	
1837 1857
    ///@{
1838 1858

	
1839 1859
    /// The type of the primal problem
1840 1860
    ProblemType primalType() const {
1841 1861
      return _getPrimalType();
1842 1862
    }
1843 1863

	
1844 1864
    /// The type of the dual problem
1845 1865
    ProblemType dualType() const {
1846 1866
      return _getDualType();
1847 1867
    }
1848 1868

	
1849 1869
    /// Return the primal value of the column
1850 1870

	
1851 1871
    /// Return the primal value of the column.
1852 1872
    /// \pre The problem is solved.
1853 1873
    Value primal(Col c) const { return _getPrimal(cols(id(c))); }
1854 1874

	
1855 1875
    /// Return the primal value of the expression
1856 1876

	
1857 1877
    /// Return the primal value of the expression, i.e. the dot
1858 1878
    /// product of the primal solution and the expression.
1859 1879
    /// \pre The problem is solved.
1860 1880
    Value primal(const Expr& e) const {
1861 1881
      double res = *e;
1862 1882
      for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
1863 1883
        res += *c * primal(c);
1864 1884
      }
1865 1885
      return res;
1866 1886
    }
1867 1887
    /// Returns a component of the primal ray
1868 1888
    
1869 1889
    /// The primal ray is solution of the modified primal problem,
1870 1890
    /// where we change each finite bound to 0, and we looking for a
1871 1891
    /// negative objective value in case of minimization, and positive
1872 1892
    /// objective value for maximization. If there is such solution,
1873 1893
    /// that proofs the unsolvability of the dual problem, and if a
1874 1894
    /// feasible primal solution exists, then the unboundness of
1875 1895
    /// primal problem.
1876 1896
    ///
1877 1897
    /// \pre The problem is solved and the dual problem is infeasible.
1878 1898
    /// \note Some solvers does not provide primal ray calculation
1879 1899
    /// functions.
1880 1900
    Value primalRay(Col c) const { return _getPrimalRay(cols(id(c))); }
1881 1901

	
1882 1902
    /// Return the dual value of the row
1883 1903

	
1884 1904
    /// Return the dual value of the row.
1885 1905
    /// \pre The problem is solved.
1886 1906
    Value dual(Row r) const { return _getDual(rows(id(r))); }
1887 1907

	
1888 1908
    /// Return the dual value of the dual expression
1889 1909

	
1890 1910
    /// Return the dual value of the dual expression, i.e. the dot
1891 1911
    /// product of the dual solution and the dual expression.
1892 1912
    /// \pre The problem is solved.
1893 1913
    Value dual(const DualExpr& e) const {
1894 1914
      double res = 0.0;
1895 1915
      for (DualExpr::ConstCoeffIt r(e); r != INVALID; ++r) {
1896 1916
        res += *r * dual(r);
1897 1917
      }
1898 1918
      return res;
1899 1919
    }
1900 1920

	
1901 1921
    /// Returns a component of the dual ray
1902 1922
    
1903 1923
    /// The dual ray is solution of the modified primal problem, where
1904 1924
    /// we change each finite bound to 0 (i.e. the objective function
1905 1925
    /// coefficients in the primal problem), and we looking for a
1906 1926
    /// ositive objective value. If there is such solution, that
1907 1927
    /// proofs the unsolvability of the primal problem, and if a
1908 1928
    /// feasible dual solution exists, then the unboundness of
1909 1929
    /// dual problem.
1910 1930
    ///
1911 1931
    /// \pre The problem is solved and the primal problem is infeasible.
1912 1932
    /// \note Some solvers does not provide dual ray calculation
1913 1933
    /// functions.
1914 1934
    Value dualRay(Row r) const { return _getDualRay(rows(id(r))); }
1915 1935

	
1916 1936
    /// Return the basis status of the column
1917 1937

	
1918 1938
    /// \see VarStatus
1919 1939
    VarStatus colStatus(Col c) const { return _getColStatus(cols(id(c))); }
1920 1940

	
1921 1941
    /// Return the basis status of the row
1922 1942

	
1923 1943
    /// \see VarStatus
1924 1944
    VarStatus rowStatus(Row r) const { return _getRowStatus(rows(id(r))); }
1925 1945

	
1926 1946
    ///The value of the objective function
1927 1947

	
1928 1948
    ///\return
1929 1949
    ///- \ref INF or -\ref INF means either infeasibility or unboundedness
1930 1950
    /// of the primal problem, depending on whether we minimize or maximize.
1931 1951
    ///- \ref NaN if no primal solution is found.
1932 1952
    ///- The (finite) objective value if an optimal solution is found.
1933 1953
    Value primal() const { return _getPrimalValue()+obj_const_comp;}
1934 1954
    ///@}
1935 1955

	
1936 1956
  protected:
1937 1957

	
1938 1958
  };
1939 1959

	
1940 1960

	
1941 1961
  /// \ingroup lp_group
1942 1962
  ///
1943 1963
  /// \brief Common base class for MIP solvers
1944 1964
  ///
1945 1965
  /// This class is an abstract base class for MIP solvers. This class
1946 1966
  /// provides a full interface for set and modify an MIP problem,
1947 1967
  /// solve it and retrieve the solution. You can use one of the
1948 1968
  /// descendants as a concrete implementation, or the \c Lp
1949 1969
  /// default MIP solver. However, if you would like to handle MIP
1950 1970
  /// solvers as reference or pointer in a generic way, you can use
1951 1971
  /// this class directly.
1952 1972
  class MipSolver : virtual public LpBase {
1953 1973
  public:
1954 1974

	
1955 1975
    /// The problem types for MIP problems
1956 1976
    enum ProblemType {
1957 1977
      ///Feasible solution hasn't been found (but may exist).
1958 1978
      UNDEFINED = 0,
1959 1979
      ///The problem has no feasible solution
1960 1980
      INFEASIBLE = 1,
1961 1981
      ///Feasible solution found
1962 1982
      FEASIBLE = 2,
1963 1983
      ///Optimal solution exists and found
1964 1984
      OPTIMAL = 3,
1965 1985
      ///The cost function is unbounded
1966 1986
      ///
1967 1987
      ///The Mip or at least the relaxed problem is unbounded
1968 1988
      UNBOUNDED = 4
1969 1989
    };
1970 1990

	
1971 1991
    ///Allocate a new MIP problem instance
1972 1992
    virtual MipSolver* newSolver() const = 0;
1973 1993
    ///Make a copy of the MIP problem
1974 1994
    virtual MipSolver* cloneSolver() const = 0;
1975 1995

	
1976 1996
    ///\name Solve the MIP
1977 1997

	
1978 1998
    ///@{
1979 1999

	
1980 2000
    /// Solve the MIP problem at hand
1981 2001
    ///
1982 2002
    ///\return The result of the optimization procedure. Possible
1983 2003
    ///values and their meanings can be found in the documentation of
1984 2004
    ///\ref SolveExitStatus.
1985 2005
    SolveExitStatus solve() { return _solve(); }
1986 2006

	
1987 2007
    ///@}
1988 2008

	
1989 2009
    ///\name Setting column type
1990 2010
    ///@{
1991 2011

	
1992 2012
    ///Possible variable (column) types (e.g. real, integer, binary etc.)
1993 2013
    enum ColTypes {
1994 2014
      ///Continuous variable (default)
1995 2015
      REAL = 0,
1996 2016
      ///Integer variable
1997 2017
      INTEGER = 1
1998 2018
    };
1999 2019

	
2000 2020
    ///Sets the type of the given column to the given type
2001 2021

	
2002 2022
    ///Sets the type of the given column to the given type.
2003 2023
    ///
2004 2024
    void colType(Col c, ColTypes col_type) {
2005 2025
      _setColType(cols(id(c)),col_type);
2006 2026
    }
2007 2027

	
2008 2028
    ///Gives back the type of the column.
2009 2029

	
2010 2030
    ///Gives back the type of the column.
2011 2031
    ///
2012 2032
    ColTypes colType(Col c) const {
2013 2033
      return _getColType(cols(id(c)));
2014 2034
    }
2015 2035
    ///@}
2016 2036

	
2017 2037
    ///\name Obtain the solution
2018 2038

	
2019 2039
    ///@{
2020 2040

	
2021 2041
    /// The type of the MIP problem
2022 2042
    ProblemType type() const {
2023 2043
      return _getType();
2024 2044
    }
2025 2045

	
2026 2046
    /// Return the value of the row in the solution
2027 2047

	
2028 2048
    ///  Return the value of the row in the solution.
2029 2049
    /// \pre The problem is solved.
2030 2050
    Value sol(Col c) const { return _getSol(cols(id(c))); }
2031 2051

	
2032 2052
    /// Return the value of the expression in the solution
2033 2053

	
2034 2054
    /// Return the value of the expression in the solution, i.e. the
2035 2055
    /// dot product of the solution and the expression.
2036 2056
    /// \pre The problem is solved.
2037 2057
    Value sol(const Expr& e) const {
2038 2058
      double res = *e;
2039 2059
      for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
2040 2060
        res += *c * sol(c);
2041 2061
      }
2042 2062
      return res;
2043 2063
    }
2044 2064
    ///The value of the objective function
2045 2065
    
2046 2066
    ///\return
2047 2067
    ///- \ref INF or -\ref INF means either infeasibility or unboundedness
2048 2068
    /// of the problem, depending on whether we minimize or maximize.
2049 2069
    ///- \ref NaN if no primal solution is found.
2050 2070
    ///- The (finite) objective value if an optimal solution is found.
2051 2071
    Value solValue() const { return _getSolValue()+obj_const_comp;}
2052 2072
    ///@}
2053 2073

	
2054 2074
  protected:
2055 2075

	
2056 2076
    virtual SolveExitStatus _solve() = 0;
2057 2077
    virtual ColTypes _getColType(int col) const = 0;
2058 2078
    virtual void _setColType(int col, ColTypes col_type) = 0;
2059 2079
    virtual ProblemType _getType() const = 0;
2060 2080
    virtual Value _getSol(int i) const = 0;
2061 2081
    virtual Value _getSolValue() const = 0;
2062 2082

	
2063 2083
  };
2064 2084

	
2065 2085

	
2066 2086

	
2067 2087
} //namespace lemon
2068 2088

	
2069 2089
#endif //LEMON_LP_BASE_H
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/lp_skeleton.h>
20 20

	
21 21
///\file
22 22
///\brief A skeleton file to implement LP solver interfaces
23 23
namespace lemon {
24 24

	
25 25
  int SkeletonSolverBase::_addCol()
26 26
  {
27 27
    return ++col_num;
28 28
  }
29 29

	
30 30
  int SkeletonSolverBase::_addRow()
31 31
  {
32 32
    return ++row_num;
33 33
  }
34 34

	
35 35
  void SkeletonSolverBase::_eraseCol(int) {}
36 36
  void SkeletonSolverBase::_eraseRow(int) {}
37 37

	
38 38
  void SkeletonSolverBase::_getColName(int, std::string &) const {}
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
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
#ifndef LEMON_LP_SKELETON_H
20 20
#define LEMON_LP_SKELETON_H
21 21

	
22 22
#include <lemon/lp_base.h>
23 23

	
24 24
///\file
25 25
///\brief Skeleton file to implement LP/MIP solver interfaces
26 26
///  
27 27
///The classes in this file do nothing, but they can serve as skeletons when
28 28
///implementing an interface to new solvers.
29 29
namespace lemon {
30 30

	
31 31
  ///A skeleton class to implement LP/MIP solver base interface
32 32
  
33 33
  ///This class does nothing, but it can serve as a skeleton when
34 34
  ///implementing an interface to new solvers.
35 35
  class SkeletonSolverBase : public virtual LpBase {
36 36
    int col_num,row_num;
37 37

	
38 38
  protected:
39 39

	
40 40
    SkeletonSolverBase()
41 41
      : col_num(-1), row_num(-1) {}
42 42

	
43 43
    /// \e
44 44
    virtual int _addCol();
45 45
    /// \e
46 46
    virtual int _addRow();
47 47
    /// \e
48 48
    virtual void _eraseCol(int i);
49 49
    /// \e
50 50
    virtual void _eraseRow(int i);
51 51

	
52 52
    /// \e
53 53
    virtual void _getColName(int col, std::string& name) const;
54 54
    /// \e
55 55
    virtual void _setColName(int col, const std::string& name);
56 56
    /// \e
57 57
    virtual int _colByName(const std::string& name) const;
58 58

	
59 59
    /// \e
60 60
    virtual void _getRowName(int row, std::string& name) const;
61 61
    /// \e
62 62
    virtual void _setRowName(int row, const std::string& name);
63 63
    /// \e
64 64
    virtual int _rowByName(const std::string& name) const;
65 65

	
66 66
    /// \e
67 67
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
68 68
    /// \e
69 69
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
70 70
    /// \e
71 71
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
72 72
    /// \e
73 73
    virtual void _getColCoeffs(int i, InsertIterator b) const;
74 74

	
75 75
    /// Set one element of the coefficient matrix
76 76
    virtual void _setCoeff(int row, int col, Value value);
77 77

	
78 78
    /// Get one element of the coefficient matrix
79 79
    virtual Value _getCoeff(int row, int col) const;
80 80

	
81 81
    /// The lower bound of a variable (column) have to be given by an
82 82
    /// extended number of type Value, i.e. a finite number of type
83 83
    /// Value or -\ref INF.
84 84
    virtual void _setColLowerBound(int i, Value value);
85 85
    /// \e
86 86

	
87 87
    /// The lower bound of a variable (column) is an
88 88
    /// extended number of type Value, i.e. a finite number of type
89 89
    /// Value or -\ref INF.
90 90
    virtual Value _getColLowerBound(int i) const;
91 91

	
92 92
    /// The upper bound of a variable (column) have to be given by an
93 93
    /// extended number of type Value, i.e. a finite number of type
94 94
    /// Value or \ref INF.
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
  };
191 193

	
192 194
  /// \brief Skeleton class for a MIP solver interface
193 195
  ///
194 196
  ///This class does nothing, but it can serve as a skeleton when
195 197
  ///implementing an interface to new solvers.
196 198
  ///\ingroup lp_group
197 199
  class MipSkeleton : public MipSolver, public SkeletonSolverBase {
198 200
  public:
199 201
    ///\e
200 202
    MipSkeleton() : MipSolver(), SkeletonSolverBase() {}
201 203
    ///\e
202 204
    virtual MipSkeleton* newSolver() const;
203 205
    ///\e
204 206
    virtual MipSkeleton* cloneSolver() const;
205 207

	
206 208
  protected:
207 209
    ///\e
208 210
    virtual SolveExitStatus _solve();
209 211

	
210 212
    ///\e
211 213
    virtual Value _getSol(int i) const;
212 214

	
213 215
    ///\e
214 216
    virtual Value _getSolValue() const;
215 217

	
216 218
    ///\e
217 219
    virtual ProblemType _getType() const;
218 220

	
219 221
    ///\e
220 222
    virtual const char* _solverName() const;
221 223
  };
222 224

	
223 225
} //namespace lemon
224 226

	
225 227
#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 <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();
98 101
  }
99 102

	
100 103
  void SoplexLp::_eraseRow(int i) {
101 104
    soplex->removeRow(i);
102 105
    _row_names_ref.erase(_row_names[i]);
103 106
    _row_names[i] = _row_names.back();
104 107
    _row_names_ref[_row_names.back()] = i;
105 108
    _row_names.pop_back();
106 109
  }
107 110

	
108 111
  void SoplexLp::_eraseColId(int i) {
109 112
    cols.eraseIndex(i);
110 113
    cols.relocateIndex(i, cols.maxIndex());
111 114
  }
112 115
  void SoplexLp::_eraseRowId(int i) {
113 116
    rows.eraseIndex(i);
114 117
    rows.relocateIndex(i, rows.maxIndex());
115 118
  }
116 119

	
117 120
  void SoplexLp::_getColName(int c, std::string &name) const {
118 121
    name = _col_names[c];
119 122
  }
120 123

	
121 124
  void SoplexLp::_setColName(int c, const std::string &name) {
122 125
    _col_names_ref.erase(_col_names[c]);
123 126
    _col_names[c] = name;
124 127
    if (!name.empty()) {
125 128
      _col_names_ref.insert(std::make_pair(name, c));
126 129
    }
127 130
  }
128 131

	
129 132
  int SoplexLp::_colByName(const std::string& name) const {
130 133
    std::map<std::string, int>::const_iterator it =
131 134
      _col_names_ref.find(name);
132 135
    if (it != _col_names_ref.end()) {
133 136
      return it->second;
134 137
    } else {
135 138
      return -1;
136 139
    }
137 140
  }
138 141

	
139 142
  void SoplexLp::_getRowName(int r, std::string &name) const {
140 143
    name = _row_names[r];
141 144
  }
142 145

	
143 146
  void SoplexLp::_setRowName(int r, const std::string &name) {
144 147
    _row_names_ref.erase(_row_names[r]);
145 148
    _row_names[r] = name;
146 149
    if (!name.empty()) {
147 150
      _row_names_ref.insert(std::make_pair(name, r));
148 151
    }
149 152
  }
150 153

	
151 154
  int SoplexLp::_rowByName(const std::string& name) const {
152 155
    std::map<std::string, int>::const_iterator it =
153 156
      _row_names_ref.find(name);
154 157
    if (it != _row_names_ref.end()) {
155 158
      return it->second;
156 159
    } else {
157 160
      return -1;
158 161
    }
159 162
  }
160 163

	
161 164

	
162 165
  void SoplexLp::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
163 166
    for (int j = 0; j < soplex->nCols(); ++j) {
164 167
      soplex->changeElement(i, j, 0.0);
165 168
    }
166 169
    for(ExprIterator it = b; it != e; ++it) {
167 170
      soplex->changeElement(i, it->first, it->second);
168 171
    }
169 172
  }
170 173

	
171 174
  void SoplexLp::_getRowCoeffs(int i, InsertIterator b) const {
172 175
    const soplex::SVector& vec = soplex->rowVector(i);
173 176
    for (int k = 0; k < vec.size(); ++k) {
174 177
      *b = std::make_pair(vec.index(k), vec.value(k));
175 178
      ++b;
176 179
    }
177 180
  }
178 181

	
179 182
  void SoplexLp::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
180 183
    for (int i = 0; i < soplex->nRows(); ++i) {
181 184
      soplex->changeElement(i, j, 0.0);
182 185
    }
183 186
    for(ExprIterator it = b; it != e; ++it) {
184 187
      soplex->changeElement(it->first, j, it->second);
185 188
    }
186 189
  }
187 190

	
188 191
  void SoplexLp::_getColCoeffs(int i, InsertIterator b) const {
189 192
    const soplex::SVector& vec = soplex->colVector(i);
190 193
    for (int k = 0; k < vec.size(); ++k) {
191 194
      *b = std::make_pair(vec.index(k), vec.value(k));
192 195
      ++b;
193 196
    }
194 197
  }
195 198

	
196 199
  void SoplexLp::_setCoeff(int i, int j, Value value) {
197 200
    soplex->changeElement(i, j, value);
198 201
  }
199 202

	
200 203
  SoplexLp::Value SoplexLp::_getCoeff(int i, int j) const {
201 204
    return soplex->rowVector(i)[j];
202 205
  }
203 206

	
204 207
  void SoplexLp::_setColLowerBound(int i, Value value) {
205 208
    LEMON_ASSERT(value != INF, "Invalid bound");
206 209
    soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
207 210
  }
208 211

	
209 212
  SoplexLp::Value SoplexLp::_getColLowerBound(int i) const {
210 213
    double value = soplex->lower(i);
211 214
    return value != -soplex::infinity ? value : -INF;
212 215
  }
213 216

	
214 217
  void SoplexLp::_setColUpperBound(int i, Value value) {
215 218
    LEMON_ASSERT(value != -INF, "Invalid bound");
216 219
    soplex->changeUpper(i, value != INF ? value : soplex::infinity);
217 220
  }
218 221

	
219 222
  SoplexLp::Value SoplexLp::_getColUpperBound(int i) const {
220 223
    double value = soplex->upper(i);
221 224
    return value != soplex::infinity ? value : INF;
222 225
  }
223 226

	
224 227
  void SoplexLp::_setRowLowerBound(int i, Value lb) {
225 228
    LEMON_ASSERT(lb != INF, "Invalid bound");
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:
322 327
      LEMON_ASSERT(false, "Wrong column status");
323 328
      return VarStatus();
324 329
    }
325 330
  }
326 331

	
327 332
  SoplexLp::VarStatus SoplexLp::_getRowStatus(int i) const {
328 333
    switch (soplex->getBasisRowStatus(i)) {
329 334
    case soplex::SPxSolver::BASIC:
330 335
      return BASIC;
331 336
    case soplex::SPxSolver::ON_UPPER:
332 337
      return UPPER;
333 338
    case soplex::SPxSolver::ON_LOWER:
334 339
      return LOWER;
335 340
    case soplex::SPxSolver::FIXED:
336 341
      return FIXED;
337 342
    case soplex::SPxSolver::ZERO:
338 343
      return FREE;
339 344
    default:
340 345
      LEMON_ASSERT(false, "Wrong row status");
341 346
      return VarStatus();
342 347
    }
343 348
  }
344 349

	
345 350
  SoplexLp::Value SoplexLp::_getPrimalRay(int i) const {
346 351
    if (_primal_ray.empty()) {
347 352
      _primal_ray.resize(soplex->nCols());
348 353
      soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
349 354
      soplex->getDualfarkas(pv);
350 355
    }
351 356
    return _primal_ray[i];
352 357
  }
353 358

	
354 359
  SoplexLp::Value SoplexLp::_getDualRay(int i) const {
355 360
    if (_dual_ray.empty()) {
356 361
      _dual_ray.resize(soplex->nRows());
357 362
      soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
358 363
      soplex->getDualfarkas(dv);
359 364
    }
360 365
    return _dual_ray[i];
361 366
  }
362 367

	
363 368
  SoplexLp::ProblemType SoplexLp::_getPrimalType() const {
364 369
    switch (soplex->status()) {
365 370
    case soplex::SPxSolver::OPTIMAL:
366 371
      return OPTIMAL;
367 372
    case soplex::SPxSolver::UNBOUNDED:
368 373
      return UNBOUNDED;
369 374
    case soplex::SPxSolver::INFEASIBLE:
370 375
      return INFEASIBLE;
371 376
    default:
372 377
      return UNDEFINED;
373 378
    }
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 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
#ifndef LEMON_SOPLEX_H
20 20
#define LEMON_SOPLEX_H
21 21

	
22 22
///\file
23 23
///\brief Header of the LEMON-SOPLEX lp solver interface.
24 24

	
25 25
#include <vector>
26 26
#include <string>
27 27

	
28 28
#include <lemon/lp_base.h>
29 29

	
30 30
// Forward declaration
31 31
namespace soplex {
32 32
  class SoPlex;
33 33
}
34 34

	
35 35
namespace lemon {
36 36

	
37 37
  /// \ingroup lp_group
38 38
  ///
39 39
  /// \brief Interface for the SOPLEX solver
40 40
  ///
41 41
  /// This class implements an interface for the SoPlex LP solver.
42 42
  /// The SoPlex library is an object oriented lp solver library
43 43
  /// developed at the Konrad-Zuse-Zentrum f�r Informationstechnik
44 44
  /// Berlin (ZIB). You can find detailed information about it at the
45 45
  /// <tt>http://soplex.zib.de</tt> address.
46 46
  class SoplexLp : public LpSolver {
47 47
  private:
48 48

	
49 49
    soplex::SoPlex* soplex;
50 50

	
51 51
    std::vector<std::string> _col_names;
52 52
    std::map<std::string, int> _col_names_ref;
53 53

	
54 54
    std::vector<std::string> _row_names;
55 55
    std::map<std::string, int> _row_names_ref;
56 56

	
57 57
  private:
58 58

	
59 59
    // these values cannot be retrieved element by element
60 60
    mutable std::vector<Value> _primal_values;
61 61
    mutable std::vector<Value> _dual_values;
62 62

	
63 63
    mutable std::vector<Value> _primal_ray;
64 64
    mutable std::vector<Value> _dual_ray;
65 65

	
66 66
    void _clear_temporals();
67 67

	
68 68
  public:
69 69

	
70 70
    /// \e
71 71
    SoplexLp();
72 72
    /// \e
73 73
    SoplexLp(const SoplexLp&);
74 74
    /// \e
75 75
    ~SoplexLp();
76 76
    /// \e
77 77
    virtual SoplexLp* newSolver() const;
78 78
    /// \e
79 79
    virtual SoplexLp* cloneSolver() const;
80 80

	
81 81
  protected:
82 82

	
83 83
    virtual const char* _solverName() const;
84 84

	
85 85
    virtual int _addCol();
86 86
    virtual int _addRow();
87 87

	
88 88
    virtual void _eraseCol(int i);
89 89
    virtual void _eraseRow(int i);
90 90

	
91 91
    virtual void _eraseColId(int i);
92 92
    virtual void _eraseRowId(int i);
93 93

	
94 94
    virtual void _getColName(int col, std::string& name) const;
95 95
    virtual void _setColName(int col, const std::string& name);
96 96
    virtual int _colByName(const std::string& name) const;
97 97

	
98 98
    virtual void _getRowName(int row, std::string& name) const;
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
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
#include <sstream>
20 20
#include <lemon/lp_skeleton.h>
21 21
#include "test_tools.h"
22 22
#include <lemon/tolerance.h>
23 23

	
24 24
#ifdef HAVE_CONFIG_H
25 25
#include <lemon/config.h>
26 26
#endif
27 27

	
28 28
#ifdef HAVE_GLPK
29 29
#include <lemon/glpk.h>
30 30
#endif
31 31

	
32 32
#ifdef HAVE_CPLEX
33 33
#include <lemon/cplex.h>
34 34
#endif
35 35

	
36 36
#ifdef HAVE_SOPLEX
37 37
#include <lemon/soplex.h>
38 38
#endif
39 39

	
40 40
#ifdef HAVE_CLP
41 41
#include <lemon/clp.h>
42 42
#endif
43 43

	
44 44
using namespace lemon;
45 45

	
46 46
void lpTest(LpSolver& lp)
47 47
{
48 48

	
49 49
  typedef LpSolver LP;
50 50

	
51 51
  std::vector<LP::Col> x(10);
52 52
  //  for(int i=0;i<10;i++) x.push_back(lp.addCol());
53 53
  lp.addColSet(x);
54 54
  lp.colLowerBound(x,1);
55 55
  lp.colUpperBound(x,1);
56 56
  lp.colBounds(x,1,2);
57 57

	
58 58
  std::vector<LP::Col> y(10);
59 59
  lp.addColSet(y);
60 60

	
61 61
  lp.colLowerBound(y,1);
62 62
  lp.colUpperBound(y,1);
63 63
  lp.colBounds(y,1,2);
64 64

	
65 65
  std::map<int,LP::Col> z;
66 66

	
67 67
  z.insert(std::make_pair(12,INVALID));
68 68
  z.insert(std::make_pair(2,INVALID));
69 69
  z.insert(std::make_pair(7,INVALID));
70 70
  z.insert(std::make_pair(5,INVALID));
71 71

	
72 72
  lp.addColSet(z);
73 73

	
74 74
  lp.colLowerBound(z,1);
75 75
  lp.colUpperBound(z,1);
76 76
  lp.colBounds(z,1,2);
77 77

	
78 78
  {
79 79
    LP::Expr e,f,g;
80 80
    LP::Col p1,p2,p3,p4,p5;
81 81
    LP::Constr c;
82 82

	
83 83
    p1=lp.addCol();
84 84
    p2=lp.addCol();
85 85
    p3=lp.addCol();
86 86
    p4=lp.addCol();
87 87
    p5=lp.addCol();
88 88

	
89 89
    e[p1]=2;
90 90
    *e=12;
91 91
    e[p1]+=2;
92 92
    *e+=12;
93 93
    e[p1]-=2;
94 94
    *e-=12;
95 95

	
96 96
    e=2;
97 97
    e=2.2;
98 98
    e=p1;
99 99
    e=f;
100 100

	
101 101
    e+=2;
102 102
    e+=2.2;
103 103
    e+=p1;
104 104
    e+=f;
105 105

	
106 106
    e-=2;
107 107
    e-=2.2;
108 108
    e-=p1;
109 109
    e-=f;
110 110

	
111 111
    e*=2;
112 112
    e*=2.2;
113 113
    e/=2;
114 114
    e/=2.2;
115 115

	
116 116
    e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+
117 117
       (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+
118 118
       (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+
119 119
       2.2*f+f*2.2+f/2.2+
120 120
       2*f+f*2+f/2+
121 121
       2.2*p1+p1*2.2+p1/2.2+
122 122
       2*p1+p1*2+p1/2
123 123
       );
124 124

	
125 125

	
126 126
    c = (e  <= f  );
127 127
    c = (e  <= 2.2);
128 128
    c = (e  <= 2  );
129 129
    c = (e  <= p1 );
130 130
    c = (2.2<= f  );
131 131
    c = (2  <= f  );
132 132
    c = (p1 <= f  );
133 133
    c = (p1 <= p2 );
134 134
    c = (p1 <= 2.2);
135 135
    c = (p1 <= 2  );
136 136
    c = (2.2<= p2 );
137 137
    c = (2  <= p2 );
138 138

	
139 139
    c = (e  >= f  );
140 140
    c = (e  >= 2.2);
141 141
    c = (e  >= 2  );
142 142
    c = (e  >= p1 );
143 143
    c = (2.2>= f  );
144 144
    c = (2  >= f  );
145 145
    c = (p1 >= f  );
146 146
    c = (p1 >= p2 );
147 147
    c = (p1 >= 2.2);
148 148
    c = (p1 >= 2  );
149 149
    c = (2.2>= p2 );
150 150
    c = (2  >= p2 );
151 151

	
152 152
    c = (e  == f  );
153 153
    c = (e  == 2.2);
154 154
    c = (e  == 2  );
155 155
    c = (e  == p1 );
156 156
    c = (2.2== f  );
157 157
    c = (2  == f  );
158 158
    c = (p1 == f  );
159 159
    //c = (p1 == p2 );
160 160
    c = (p1 == 2.2);
161 161
    c = (p1 == 2  );
162 162
    c = (2.2== p2 );
163 163
    c = (2  == p2 );
164 164

	
165 165
    c = ((2 <= e) <= 3);
166 166
    c = ((2 <= p1) <= 3);
167 167

	
168 168
    c = ((2 >= e) >= 3);
169 169
    c = ((2 >= p1) >= 3);
170 170

	
171 171
    e[x[3]]=2;
172 172
    e[x[3]]=4;
173 173
    e[x[3]]=1;
174 174
    *e=12;
175 175

	
176 176
    lp.addRow(-LP::INF,e,23);
177 177
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
178 178
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
179 179

	
180 180
    lp.addRow(x[1]+x[3]<=x[5]-3);
181 181
    lp.addRow((-7<=x[1]+x[3]-12)<=3);
182 182
    lp.addRow(x[1]<=x[5]);
183 183

	
184 184
    std::ostringstream buf;
185 185

	
186 186

	
187 187
    e=((p1+p2)+(p1-0.99*p2));
188 188
    //e.prettyPrint(std::cout);
189 189
    //(e<=2).prettyPrint(std::cout);
190 190
    double tolerance=0.001;
191 191
    e.simplify(tolerance);
192 192
    buf << "Coeff. of p2 should be 0.01";
193 193
    check(e[p2]>0, buf.str());
194 194

	
195 195
    tolerance=0.02;
196 196
    e.simplify(tolerance);
197 197
    buf << "Coeff. of p2 should be 0";
198 198
    check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
199 199

	
200 200
    //Test for clone/new
201 201
    LP* lpnew = lp.newSolver();
202 202
    LP* lpclone = lp.cloneSolver();
203 203
    delete lpnew;
204 204
    delete lpclone;
205 205

	
206 206
  }
207 207

	
208 208
  {
209 209
    LP::DualExpr e,f,g;
210 210
    LP::Row p1 = INVALID, p2 = INVALID, p3 = INVALID,
211 211
      p4 = INVALID, p5 = INVALID;
212 212

	
213 213
    e[p1]=2;
214 214
    e[p1]+=2;
215 215
    e[p1]-=2;
216 216

	
217 217
    e=p1;
218 218
    e=f;
219 219

	
220 220
    e+=p1;
221 221
    e+=f;
222 222

	
223 223
    e-=p1;
224 224
    e-=f;
225 225

	
226 226
    e*=2;
227 227
    e*=2.2;
228 228
    e/=2;
229 229
    e/=2.2;
230 230

	
231 231
    e=((p1+p2)+(p1-p2)+
232 232
       (p1+f)+(f+p1)+(f+g)+
233 233
       (p1-f)+(f-p1)+(f-g)+
234 234
       2.2*f+f*2.2+f/2.2+
235 235
       2*f+f*2+f/2+
236 236
       2.2*p1+p1*2.2+p1/2.2+
237 237
       2*p1+p1*2+p1/2
238 238
       );
239 239
  }
240 240

	
241 241
}
242 242

	
243 243
void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat,
244 244
                   double exp_opt) {
245 245
  using std::string;
246 246
  lp.solve();
247 247

	
248 248
  std::ostringstream buf;
249 249
  buf << "PrimalType should be: " << int(stat) << int(lp.primalType());
250 250

	
251 251
  check(lp.primalType()==stat, buf.str());
252 252

	
253 253
  if (stat ==  LpSolver::OPTIMAL) {
254 254
    std::ostringstream sbuf;
255 255
    sbuf << "Wrong optimal value (" << lp.primal() <<") with "
256 256
         << lp.solverName() <<"\n     the right optimum is " << exp_opt;
257 257
    check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
258 258
  }
259 259
}
260 260

	
261 261
void aTest(LpSolver & lp)
262 262
{
263 263
  typedef LpSolver LP;
264 264

	
265 265
 //The following example is very simple
266 266

	
267 267
  typedef LpSolver::Row Row;
268 268
  typedef LpSolver::Col Col;
269 269

	
270 270

	
271 271
  Col x1 = lp.addCol();
272 272
  Col x2 = lp.addCol();
273 273

	
274 274

	
275 275
  //Constraints
276 276
  Row upright=lp.addRow(x1+2*x2 <=1);
277 277
  lp.addRow(x1+x2 >=-1);
278 278
  lp.addRow(x1-x2 <=1);
279 279
  lp.addRow(x1-x2 >=-1);
280 280
  //Nonnegativity of the variables
281 281
  lp.colLowerBound(x1, 0);
282 282
  lp.colLowerBound(x2, 0);
283 283
  //Objective function
284 284
  lp.obj(x1+x2);
285 285

	
286 286
  lp.sense(lp.MAX);
287 287

	
288 288
  //Testing the problem retrieving routines
289 289
  check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
290 290
  check(lp.sense() == lp.MAX,"This is a maximization!");
291 291
  check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
292 292
  check(lp.colLowerBound(x1)==0,
293 293
        "The lower bound for variable x1 should be 0.");
294 294
  check(lp.colUpperBound(x1)==LpSolver::INF,
295 295
        "The upper bound for variable x1 should be infty.");
296 296
  check(lp.rowLowerBound(upright) == -LpSolver::INF,
297 297
        "The lower bound for the first row should be -infty.");
298 298
  check(lp.rowUpperBound(upright)==1,
299 299
        "The upper bound for the first row should be 1.");
300 300
  LpSolver::Expr e = lp.row(upright);
301 301
  check(e[x1] == 1, "The first coefficient should 1.");
302 302
  check(e[x2] == 2, "The second coefficient should 1.");
303 303

	
304 304
  lp.row(upright, x1+x2 <=1);
305 305
  e = lp.row(upright);
306 306
  check(e[x1] == 1, "The first coefficient should 1.");
307 307
  check(e[x2] == 1, "The second coefficient should 1.");
308 308

	
309 309
  LpSolver::DualExpr de = lp.col(x1);
310 310
  check(  de[upright] == 1, "The first coefficient should 1.");
311 311

	
312 312
  LpSolver* clp = lp.cloneSolver();
313 313

	
314 314
  //Testing the problem retrieving routines
315 315
  check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
316 316
  check(clp->sense() == clp->MAX,"This is a maximization!");
317 317
  check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
318 318
  //  std::cout<<lp.colLowerBound(x1)<<std::endl;
319 319
  check(clp->colLowerBound(x1)==0,
320 320
        "The lower bound for variable x1 should be 0.");
321 321
  check(clp->colUpperBound(x1)==LpSolver::INF,
322 322
        "The upper bound for variable x1 should be infty.");
323 323

	
324 324
  check(lp.rowLowerBound(upright)==-LpSolver::INF,
325 325
        "The lower bound for the first row should be -infty.");
326 326
  check(lp.rowUpperBound(upright)==1,
327 327
        "The upper bound for the first row should be 1.");
328 328
  e = clp->row(upright);
329 329
  check(e[x1] == 1, "The first coefficient should 1.");
330 330
  check(e[x2] == 1, "The second coefficient should 1.");
331 331

	
332 332
  de = clp->col(x1);
333 333
  check(de[upright] == 1, "The first coefficient should 1.");
334 334

	
335 335
  delete clp;
336 336

	
337 337
  //Maximization of x1+x2
338 338
  //over the triangle with vertices (0,0) (0,1) (1,0)
339 339
  double expected_opt=1;
340 340
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
341 341

	
342 342
  //Minimization
343 343
  lp.sense(lp.MIN);
344 344
  expected_opt=0;
345 345
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
346 346

	
347 347
  //Vertex (-1,0) instead of (0,0)
348 348
  lp.colLowerBound(x1, -LpSolver::INF);
349 349
  expected_opt=-1;
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
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
#include "test_tools.h"
20 20

	
21 21
#ifdef HAVE_CONFIG_H
22 22
#include <lemon/config.h>
23 23
#endif
24 24

	
25 25
#ifdef HAVE_CPLEX
26 26
#include <lemon/cplex.h>
27 27
#endif
28 28

	
29 29
#ifdef HAVE_GLPK
30 30
#include <lemon/glpk.h>
31 31
#endif
32 32

	
33 33
#ifdef HAVE_CBC
34 34
#include <lemon/cbc.h>
35 35
#endif
36 36

	
37 37

	
38 38
using namespace lemon;
39 39

	
40 40
void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat,
41 41
                   double exp_opt) {
42 42
  using std::string;
43 43

	
44 44
  mip.solve();
45 45
  //int decimal,sign;
46 46
  std::ostringstream buf;
47 47
  buf << "Type should be: " << int(stat)<<" and it is "<<int(mip.type());
48 48

	
49 49

	
50 50
  //  itoa(stat,buf1, 10);
51 51
  check(mip.type()==stat, buf.str());
52 52

	
53 53
  if (stat ==  MipSolver::OPTIMAL) {
54 54
    std::ostringstream sbuf;
55 55
    buf << "Wrong optimal value: the right optimum is " << exp_opt;
56 56
    check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str());
57 57
    //+ecvt(exp_opt,2)
58 58
  }
59 59
}
60 60

	
61 61
void aTest(MipSolver& mip)
62 62
{
63 63
  //The following example is very simple
64 64

	
65 65

	
66 66
  typedef MipSolver::Row Row;
67 67
  typedef MipSolver::Col Col;
68 68

	
69 69

	
70 70
  Col x1 = mip.addCol();
71 71
  Col x2 = mip.addCol();
72 72

	
73 73

	
74 74
  //Objective function
75 75
  mip.obj(x1);
76 76

	
77 77
  mip.max();
78 78

	
79 79
  //Unconstrained optimization
80 80
  mip.solve();
81 81
  //Check it out!
82 82

	
83 83
  //Constraints
84 84
  mip.addRow(2 * x1 + x2 <= 2);
85 85
  Row y2 = mip.addRow(x1 - 2 * x2 <= 0);
86 86

	
87 87
  //Nonnegativity of the variable x1
88 88
  mip.colLowerBound(x1, 0);
89 89

	
90 90

	
91 91
  //Maximization of x1
92 92
  //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
93 93
  double expected_opt=4.0/5.0;
94 94
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
95 95

	
96 96

	
97 97
  //Restrict x2 to integer
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
1 1
#!/bin/bash
2 2

	
3 3
set -e
4 4

	
5 5
if [ $# -eq 0 -o x$1 = "x-h" -o x$1 = "x-help" -o x$1 = "x--help" ]; then
6 6
    echo "Usage:"
7 7
    echo "  $0 source-file(s)"
8 8
    exit
9 9
fi
10 10

	
11 11
for i in $@
12 12
do
13 13
    echo Update $i...
14 14
    TMP=`mktemp`
15 15
    sed -e "s/\<undirected graph\>/_gr_aph_label_/g"\
16 16
        -e "s/\<undirected graphs\>/_gr_aph_label_s/g"\
17 17
        -e "s/\<undirected edge\>/_ed_ge_label_/g"\
18 18
        -e "s/\<undirected edges\>/_ed_ge_label_s/g"\
19 19
        -e "s/\<directed graph\>/_digr_aph_label_/g"\
20 20
        -e "s/\<directed graphs\>/_digr_aph_label_s/g"\
21 21
        -e "s/\<directed edge\>/_ar_c_label_/g"\
22 22
        -e "s/\<directed edges\>/_ar_c_label_s/g"\
23 23
        -e "s/UGraph/_Gr_aph_label_/g"\
24 24
        -e "s/u[Gg]raph/_gr_aph_label_/g"\
25 25
        -e "s/Graph\>/_Digr_aph_label_/g"\
26 26
        -e "s/\<graph\>/_digr_aph_label_/g"\
27 27
        -e "s/Graphs\>/_Digr_aph_label_s/g"\
28 28
        -e "s/\<graphs\>/_digr_aph_label_s/g"\
29 29
        -e "s/\([Gg]\)raph\([a-z]\)/_\1r_aph_label_\2/g"\
30 30
        -e "s/\([a-z_]\)graph/\1_gr_aph_label_/g"\
31 31
        -e "s/Graph/_Digr_aph_label_/g"\
32 32
        -e "s/graph/_digr_aph_label_/g"\
33 33
        -e "s/UEdge/_Ed_ge_label_/g"\
34 34
        -e "s/u[Ee]dge/_ed_ge_label_/g"\
35 35
        -e "s/IncEdgeIt/_In_cEd_geIt_label_/g"\
36 36
        -e "s/Edge\>/_Ar_c_label_/g"\
37 37
        -e "s/\<edge\>/_ar_c_label_/g"\
38 38
        -e "s/_edge\>/_ar_c_label_/g"\
39 39
        -e "s/Edges\>/_Ar_c_label_s/g"\
40 40
        -e "s/\<edges\>/_ar_c_label_s/g"\
41 41
        -e "s/_edges\>/_ar_c_label_s/g"\
42 42
        -e "s/\([Ee]\)dge\([a-z]\)/_\1d_ge_label_\2/g"\
43 43
        -e "s/\([a-z]\)edge/\1_ed_ge_label_/g"\
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)