gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Faster add row operation (#203) One virtual function call instead of more
0 13 0
default
13 files changed with 137 insertions and 4 deletions:
↑ Collapse diff ↑
Show white space 1024 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 58
    messageLevel(MESSAGE_NOTHING);
59 59
  }
60 60

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

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

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

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

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

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

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

	
97
  int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
98
    std::vector<int> indexes;
99
    std::vector<Value> values;
100

	
101
    for(ExprIterator it = b; it != e; ++it) {
102
      indexes.push_back(it->first);
103
      values.push_back(it->second);
104
    }
105

	
106
    _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
107
    return _prob->numberRows() - 1;
108
  }
97 109

	
98 110
  void CbcMip::_eraseCol(int i) {
99 111
    _prob->deleteColumn(i);
100 112
  }
101 113

	
102 114
  void CbcMip::_eraseRow(int i) {
103 115
    _prob->deleteRow(i);
104 116
  }
105 117

	
106 118
  void CbcMip::_eraseColId(int i) {
107 119
    cols.eraseIndex(i);
108 120
  }
109 121

	
110 122
  void CbcMip::_eraseRowId(int i) {
111 123
    rows.eraseIndex(i);
112 124
  }
113 125

	
114 126
  void CbcMip::_getColName(int c, std::string& name) const {
115 127
    name = _prob->getColumnName(c);
116 128
  }
117 129

	
118 130
  void CbcMip::_setColName(int c, const std::string& name) {
119 131
    _prob->setColumnName(c, name.c_str());
120 132
  }
121 133

	
122 134
  int CbcMip::_colByName(const std::string& name) const {
123 135
    return _prob->column(name.c_str());
124 136
  }
125 137

	
126 138
  void CbcMip::_getRowName(int r, std::string& name) const {
127 139
    name = _prob->getRowName(r);
128 140
  }
129 141

	
130 142
  void CbcMip::_setRowName(int r, const std::string& name) {
131 143
    _prob->setRowName(r, name.c_str());
132 144
  }
133 145

	
134 146
  int CbcMip::_rowByName(const std::string& name) const {
135 147
    return _prob->row(name.c_str());
136 148
  }
137 149

	
138 150
  void CbcMip::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
139 151
    for (ExprIterator it = b; it != e; ++it) {
140 152
      _prob->setElement(i, it->first, it->second);
141 153
    }
142 154
  }
143 155

	
144 156
  void CbcMip::_getRowCoeffs(int ix, InsertIterator b) const {
145 157
    int length = _prob->numberRows();
146 158

	
147 159
    std::vector<int> indices(length);
148 160
    std::vector<Value> values(length);
149 161

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

	
152 164
    for (int i = 0; i < length; ++i) {
153 165
      *b = std::make_pair(indices[i], values[i]);
154 166
      ++b;
155 167
    }
156 168
  }
157 169

	
158 170
  void CbcMip::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
159 171
    for (ExprIterator it = b; it != e; ++it) {
160 172
      _prob->setElement(it->first, ix, it->second);
161 173
    }
162 174
  }
163 175

	
164 176
  void CbcMip::_getColCoeffs(int ix, InsertIterator b) const {
165 177
    int length = _prob->numberColumns();
166 178

	
167 179
    std::vector<int> indices(length);
168 180
    std::vector<Value> values(length);
169 181

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

	
172 184
    for (int i = 0; i < length; ++i) {
173 185
      *b = std::make_pair(indices[i], values[i]);
174 186
      ++b;
175 187
    }
176 188
  }
177 189

	
178 190
  void CbcMip::_setCoeff(int ix, int jx, Value value) {
179 191
    _prob->setElement(ix, jx, value);
180 192
  }
181 193

	
182 194
  CbcMip::Value CbcMip::_getCoeff(int ix, int jx) const {
183 195
    return _prob->getElement(ix, jx);
184 196
  }
185 197

	
186 198

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

	
192 204
  CbcMip::Value CbcMip::_getColLowerBound(int i) const {
193 205
    double val = _prob->getColumnLower(i);
194 206
    return val == - COIN_DBL_MAX ? - INF : val;
195 207
  }
196 208

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

	
202 214
  CbcMip::Value CbcMip::_getColUpperBound(int i) const {
203 215
    double val = _prob->getColumnUpper(i);
204 216
    return val == COIN_DBL_MAX ? INF : val;
205 217
  }
206 218

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

	
212 224
  CbcMip::Value CbcMip::_getRowLowerBound(int i) const {
213 225
    double val = _prob->getRowLower(i);
214 226
    return val == - COIN_DBL_MAX ? - INF : val;
215 227
  }
216 228

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

	
222 234
  CbcMip::Value CbcMip::_getRowUpperBound(int i) const {
223 235
    double val = _prob->getRowUpper(i);
224 236
    return val == COIN_DBL_MAX ? INF : val;
225 237
  }
226 238

	
227 239
  void CbcMip::_setObjCoeffs(ExprIterator b, ExprIterator e) {
228 240
    int num = _prob->numberColumns();
229 241
    for (int i = 0; i < num; ++i) {
230 242
      _prob->setColumnObjective(i, 0.0);
231 243
    }
232 244
    for (ExprIterator it = b; it != e; ++it) {
233 245
      _prob->setColumnObjective(it->first, it->second);
234 246
    }
235 247
  }
236 248

	
237 249
  void CbcMip::_getObjCoeffs(InsertIterator b) const {
238 250
    int num = _prob->numberColumns();
239 251
    for (int i = 0; i < num; ++i) {
240 252
      Value coef = _prob->getColumnObjective(i);
241 253
      if (coef != 0.0) {
242 254
        *b = std::make_pair(i, coef);
243 255
        ++b;
244 256
      }
245 257
    }
246 258
  }
247 259

	
248 260
  void CbcMip::_setObjCoeff(int i, Value obj_coef) {
249 261
    _prob->setColumnObjective(i, obj_coef);
250 262
  }
251 263

	
252 264
  CbcMip::Value CbcMip::_getObjCoeff(int i) const {
253 265
    return _prob->getColumnObjective(i);
254 266
  }
255 267

	
256 268
  CbcMip::SolveExitStatus CbcMip::_solve() {
257 269

	
258 270
    if (_osi_solver) {
259 271
      delete _osi_solver;
260 272
    }
261 273
#ifdef COIN_HAS_CLP
262 274
    _osi_solver = new OsiClpSolverInterface();
263 275
#elif COIN_HAS_OSL
264 276
    _osi_solver = new OsiOslSolverInterface();
265 277
#else
266 278
#error Cannot instantiate Osi solver
267 279
#endif
268 280

	
269 281
    _osi_solver->loadFromCoinModel(*_prob);
270 282

	
271 283
    if (_cbc_model) {
272 284
      delete _cbc_model;
273 285
    }
274 286
    _cbc_model= new CbcModel(*_osi_solver);
275 287

	
276 288
    _osi_solver->messageHandler()->setLogLevel(_message_level);
277 289
    _cbc_model->setLogLevel(_message_level);
278 290

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

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

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

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

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

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

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

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

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

	
319 331
#ifdef COIN_HAS_CLP
320 332
      OsiClpSolverInterface* osiclp =
321 333
        dynamic_cast<OsiClpSolverInterface*>(_cbc_model->solver());
322 334
      if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) {
323 335
        osiclp->setupForRepeatedUse(2, 0);
324 336
      }
325 337
#endif
326 338

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

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

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

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

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

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

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

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

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

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

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

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

	
388 400
  void CbcMip::_setSense(Sense sense) {
389 401
    switch (sense) {
390 402
    case MIN:
391 403
      _prob->setOptimizationDirection(1.0);
392 404
      break;
393 405
    case MAX:
394 406
      _prob->setOptimizationDirection(- 1.0);
395 407
      break;
396 408
    }
397 409
  }
398 410

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

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

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

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

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

	
443 455
  void CbcMip::_messageLevel(MessageLevel level) {
444 456
    switch (level) {
445 457
    case MESSAGE_NOTHING:
446 458
      _message_level = 0;
447 459
      break;
448 460
    case MESSAGE_ERROR:
449 461
      _message_level = 1;
450 462
      break;
451 463
    case MESSAGE_WARNING:
452 464
      _message_level = 1;
453 465
      break;
454 466
    case MESSAGE_NORMAL:
455 467
      _message_level = 2;
456 468
      break;
457 469
    case MESSAGE_VERBOSE:
458 470
      _message_level = 3;
459 471
      break;
460 472
    }
461 473
  }
462 474

	
463 475
} //END OF NAMESPACE LEMON
Show white space 1024 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
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
65 66

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

	
69 70
    virtual void _eraseColId(int i);
70 71
    virtual void _eraseRowId(int i);
71 72

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

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

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

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

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

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

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

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

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

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

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

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

	
116 117
    virtual void _clear();
117 118

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

	
121 122
    int _message_level;
122 123

	
123 124
    
124 125

	
125 126
  };
126 127

	
127 128
}
128 129

	
129 130
#endif
Show white space 1024 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 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 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
  int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
82
    std::vector<int> indexes;
83
    std::vector<Value> values;
84

	
85
    for(ExprIterator it = b; it != e; ++it) {
86
      indexes.push_back(it->first);
87
      values.push_back(it->second);
88
    }
89

	
90
    _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
91
    return _prob->numberRows() - 1;
92
  }
93

	
81 94

	
82 95
  void ClpLp::_eraseCol(int c) {
83 96
    _col_names_ref.erase(_prob->getColumnName(c));
84 97
    _prob->deleteColumns(1, &c);
85 98
  }
86 99

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

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

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

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

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

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

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

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

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

	
130 143

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
379 392

	
380 393
  ClpLp::ProblemType ClpLp::_getPrimalType() const {
381 394
    if (_prob->isProvenOptimal()) {
382 395
      return OPTIMAL;
383 396
    } else if (_prob->isProvenPrimalInfeasible()) {
384 397
      return INFEASIBLE;
385 398
    } else if (_prob->isProvenDualInfeasible()) {
386 399
      return UNBOUNDED;
387 400
    } else {
388 401
      return UNDEFINED;
389 402
    }
390 403
  }
391 404

	
392 405
  ClpLp::ProblemType ClpLp::_getDualType() const {
393 406
    if (_prob->isProvenOptimal()) {
394 407
      return OPTIMAL;
395 408
    } else if (_prob->isProvenDualInfeasible()) {
396 409
      return INFEASIBLE;
397 410
    } else if (_prob->isProvenPrimalInfeasible()) {
398 411
      return INFEASIBLE;
399 412
    } else {
400 413
      return UNDEFINED;
401 414
    }
402 415
  }
403 416

	
404 417
  void ClpLp::_setSense(ClpLp::Sense sense) {
405 418
    switch (sense) {
406 419
    case MIN:
407 420
      _prob->setOptimizationDirection(1);
408 421
      break;
409 422
    case MAX:
410 423
      _prob->setOptimizationDirection(-1);
411 424
      break;
412 425
    }
413 426
  }
414 427

	
415 428
  ClpLp::Sense ClpLp::_getSense() const {
416 429
    double dir = _prob->optimizationDirection();
417 430
    if (dir > 0.0) {
418 431
      return MIN;
419 432
    } else {
420 433
      return MAX;
421 434
    }
422 435
  }
423 436

	
424 437
  void ClpLp::_clear() {
425 438
    delete _prob;
426 439
    _prob = new ClpSimplex();
427 440
    rows.clear();
428 441
    cols.clear();
429 442
    _col_names_ref.clear();
430 443
    _clear_temporals();
431 444
  }
432 445

	
433 446
  void ClpLp::_messageLevel(MessageLevel level) {
434 447
    switch (level) {
435 448
    case MESSAGE_NOTHING:
436 449
      _prob->setLogLevel(0);
437 450
      break;
438 451
    case MESSAGE_ERROR:
439 452
      _prob->setLogLevel(1);
440 453
      break;
441 454
    case MESSAGE_WARNING:
442 455
      _prob->setLogLevel(2);
443 456
      break;
444 457
    case MESSAGE_NORMAL:
445 458
      _prob->setLogLevel(3);
446 459
      break;
447 460
    case MESSAGE_VERBOSE:
448 461
      _prob->setLogLevel(4);
449 462
      break;
450 463
    }
451 464
  }
452 465

	
453 466
} //END OF NAMESPACE LEMON
Show white space 1024 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
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
78 79

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

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

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

	
89 90
    virtual void _getRowName(int row, std::string& name) const;
90 91
    virtual void _setRowName(int row, const std::string& name);
91 92
    virtual int _rowByName(const std::string& name) const;
92 93

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

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

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

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

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

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

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

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

	
121 122
    virtual SolveExitStatus _solve();
122 123

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

	
126 127
    virtual Value _getPrimalValue() const;
127 128

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

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

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

	
137 138
    virtual void _clear();
138 139

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

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

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

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

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

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

	
158 159
  };
159 160

	
160 161
} //END OF NAMESPACE LEMON
161 162

	
162 163
#endif //LEMON_CLP_H
163 164

	
Show white space 1024 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 75
    messageLevel(MESSAGE_NOTHING);
76 76
  }
77 77

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

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

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

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

	
105 105

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

	
114
  int CplexBase::_addRow(Value lb, ExprIterator b, 
115
                         ExprIterator e, Value ub) {
116
    int i = CPXgetnumrows(cplexEnv(), _prob);
117
    if (lb == -INF) {
118
      const char s = 'L';
119
      CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
120
    } else if (ub == INF) {
121
      const char s = 'G';
122
      CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
123
    } else if (lb == ub){
124
      const char s = 'E';
125
      CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
126
    } else {
127
      const char s = 'R';
128
      double len = ub - lb;
129
      CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0);
130
    }
131

	
132
    std::vector<int> indices;
133
    std::vector<int> rowlist;
134
    std::vector<Value> values;
135

	
136
    for(ExprIterator it=b; it!=e; ++it) {
137
      indices.push_back(it->first);
138
      values.push_back(it->second);
139
      rowlist.push_back(i);
140
    }
141

	
142
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
143
                   &rowlist.front(), &indices.front(), &values.front());
144

	
145
    return i;
146
  }
114 147

	
115 148
  void CplexBase::_eraseCol(int i) {
116 149
    CPXdelcols(cplexEnv(), _prob, i, i);
117 150
  }
118 151

	
119 152
  void CplexBase::_eraseRow(int i) {
120 153
    CPXdelrows(cplexEnv(), _prob, i, i);
121 154
  }
122 155

	
123 156
  void CplexBase::_eraseColId(int i) {
124 157
    cols.eraseIndex(i);
125 158
    cols.shiftIndices(i);
126 159
  }
127 160
  void CplexBase::_eraseRowId(int i) {
128 161
    rows.eraseIndex(i);
129 162
    rows.shiftIndices(i);
130 163
  }
131 164

	
132 165
  void CplexBase::_getColName(int col, std::string &name) const {
133 166
    int size;
134 167
    CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
135 168
    if (size == 0) {
136 169
      name.clear();
137 170
      return;
138 171
    }
139 172

	
140 173
    size *= -1;
141 174
    std::vector<char> buf(size);
142 175
    char *cname;
143 176
    int tmp;
144 177
    CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
145 178
                  &tmp, col, col);
146 179
    name = cname;
147 180
  }
148 181

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

	
155 188
  int CplexBase::_colByName(const std::string& name) const {
156 189
    int index;
157 190
    if (CPXgetcolindex(cplexEnv(), _prob,
158 191
                       const_cast<char*>(name.c_str()), &index) == 0) {
159 192
      return index;
160 193
    }
161 194
    return -1;
162 195
  }
163 196

	
164 197
  void CplexBase::_getRowName(int row, std::string &name) const {
165 198
    int size;
166 199
    CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
167 200
    if (size == 0) {
168 201
      name.clear();
169 202
      return;
170 203
    }
171 204

	
172 205
    size *= -1;
173 206
    std::vector<char> buf(size);
174 207
    char *cname;
175 208
    int tmp;
176 209
    CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
177 210
                  &tmp, row, row);
178 211
    name = cname;
179 212
  }
180 213

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

	
187 220
  int CplexBase::_rowByName(const std::string& name) const {
188 221
    int index;
189 222
    if (CPXgetrowindex(cplexEnv(), _prob,
190 223
                       const_cast<char*>(name.c_str()), &index) == 0) {
191 224
      return index;
192 225
    }
193 226
    return -1;
194 227
  }
195 228

	
196 229
  void CplexBase::_setRowCoeffs(int i, ExprIterator b,
197 230
                                      ExprIterator e)
198 231
  {
199 232
    std::vector<int> indices;
200 233
    std::vector<int> rowlist;
201 234
    std::vector<Value> values;
202 235

	
203 236
    for(ExprIterator it=b; it!=e; ++it) {
204 237
      indices.push_back(it->first);
205 238
      values.push_back(it->second);
206 239
      rowlist.push_back(i);
207 240
    }
208 241

	
209 242
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
210 243
                   &rowlist.front(), &indices.front(), &values.front());
211 244
  }
212 245

	
213 246
  void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
214 247
    int tmp1, tmp2, tmp3, length;
215 248
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
216 249

	
217 250
    length = -length;
218 251
    std::vector<int> indices(length);
219 252
    std::vector<double> values(length);
220 253

	
221 254
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
222 255
               &indices.front(), &values.front(),
223 256
               length, &tmp3, i, i);
224 257

	
225 258
    for (int i = 0; i < length; ++i) {
226 259
      *b = std::make_pair(indices[i], values[i]);
227 260
      ++b;
228 261
    }
229 262
  }
230 263

	
231 264
  void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
232 265
    std::vector<int> indices;
233 266
    std::vector<int> collist;
234 267
    std::vector<Value> values;
235 268

	
236 269
    for(ExprIterator it=b; it!=e; ++it) {
237 270
      indices.push_back(it->first);
238 271
      values.push_back(it->second);
239 272
      collist.push_back(i);
240 273
    }
241 274

	
242 275
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
243 276
                   &indices.front(), &collist.front(), &values.front());
244 277
  }
245 278

	
246 279
  void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
247 280

	
248 281
    int tmp1, tmp2, tmp3, length;
249 282
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
250 283

	
251 284
    length = -length;
252 285
    std::vector<int> indices(length);
253 286
    std::vector<double> values(length);
254 287

	
255 288
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
256 289
               &indices.front(), &values.front(),
257 290
               length, &tmp3, i, i);
258 291

	
259 292
    for (int i = 0; i < length; ++i) {
260 293
      *b = std::make_pair(indices[i], values[i]);
261 294
      ++b;
262 295
    }
263 296

	
264 297
  }
265 298

	
266 299
  void CplexBase::_setCoeff(int row, int col, Value value) {
267 300
    CPXchgcoef(cplexEnv(), _prob, row, col, value);
268 301
  }
269 302

	
270 303
  CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
271 304
    CplexBase::Value value;
272 305
    CPXgetcoef(cplexEnv(), _prob, row, col, &value);
273 306
    return value;
274 307
  }
275 308

	
276 309
  void CplexBase::_setColLowerBound(int i, Value value) {
277 310
    const char s = 'L';
278 311
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
279 312
  }
280 313

	
281 314
  CplexBase::Value CplexBase::_getColLowerBound(int i) const {
282 315
    CplexBase::Value res;
283 316
    CPXgetlb(cplexEnv(), _prob, &res, i, i);
284 317
    return res <= -CPX_INFBOUND ? -INF : res;
285 318
  }
286 319

	
287 320
  void CplexBase::_setColUpperBound(int i, Value value)
288 321
  {
289 322
    const char s = 'U';
290 323
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
291 324
  }
292 325

	
293 326
  CplexBase::Value CplexBase::_getColUpperBound(int i) const {
294 327
    CplexBase::Value res;
295 328
    CPXgetub(cplexEnv(), _prob, &res, i, i);
296 329
    return res >= CPX_INFBOUND ? INF : res;
297 330
  }
298 331

	
299 332
  CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
300 333
    char s;
301 334
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
302 335
    CplexBase::Value res;
303 336

	
304 337
    switch (s) {
305 338
    case 'G':
306 339
    case 'R':
307 340
    case 'E':
308 341
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
309 342
      return res <= -CPX_INFBOUND ? -INF : res;
310 343
    default:
311 344
      return -INF;
312 345
    }
313 346
  }
314 347

	
315 348
  CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
316 349
    char s;
317 350
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
318 351
    CplexBase::Value res;
319 352

	
320 353
    switch (s) {
321 354
    case 'L':
322 355
    case 'E':
323 356
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
324 357
      return res >= CPX_INFBOUND ? INF : res;
325 358
    case 'R':
326 359
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
327 360
      {
328 361
        double rng;
329 362
        CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
330 363
        res += rng;
331 364
      }
332 365
      return res >= CPX_INFBOUND ? INF : res;
333 366
    default:
334 367
      return INF;
335 368
    }
336 369
  }
337 370

	
338 371
  //This is easier to implement
339 372
  void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
340 373
    if (lb == -INF) {
341 374
      const char s = 'L';
342 375
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
343 376
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
344 377
    } else if (ub == INF) {
345 378
      const char s = 'G';
346 379
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
347 380
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
348 381
    } else if (lb == ub){
349 382
      const char s = 'E';
350 383
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
351 384
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
352 385
    } else {
353 386
      const char s = 'R';
354 387
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
355 388
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
356 389
      double len = ub - lb;
357 390
      CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
358 391
    }
359 392
  }
360 393

	
361 394
  void CplexBase::_setRowLowerBound(int i, Value lb)
362 395
  {
363 396
    LEMON_ASSERT(lb != INF, "Invalid bound");
364 397
    _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
365 398
  }
366 399

	
367 400
  void CplexBase::_setRowUpperBound(int i, Value ub)
368 401
  {
369 402

	
370 403
    LEMON_ASSERT(ub != -INF, "Invalid bound");
371 404
    _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
372 405
  }
373 406

	
374 407
  void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
375 408
  {
376 409
    std::vector<int> indices;
377 410
    std::vector<Value> values;
378 411
    for(ExprIterator it=b; it!=e; ++it) {
379 412
      indices.push_back(it->first);
380 413
      values.push_back(it->second);
381 414
    }
382 415
    CPXchgobj(cplexEnv(), _prob, values.size(),
383 416
              &indices.front(), &values.front());
384 417

	
385 418
  }
386 419

	
387 420
  void CplexBase::_getObjCoeffs(InsertIterator b) const
388 421
  {
389 422
    int num = CPXgetnumcols(cplexEnv(), _prob);
390 423
    std::vector<Value> x(num);
391 424

	
392 425
    CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
393 426
    for (int i = 0; i < num; ++i) {
394 427
      if (x[i] != 0.0) {
395 428
        *b = std::make_pair(i, x[i]);
396 429
        ++b;
397 430
      }
398 431
    }
399 432
  }
400 433

	
401 434
  void CplexBase::_setObjCoeff(int i, Value obj_coef)
402 435
  {
403 436
    CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
404 437
  }
405 438

	
406 439
  CplexBase::Value CplexBase::_getObjCoeff(int i) const
407 440
  {
408 441
    Value x;
409 442
    CPXgetobj(cplexEnv(), _prob, &x, i, i);
410 443
    return x;
411 444
  }
412 445

	
413 446
  void CplexBase::_setSense(CplexBase::Sense sense) {
414 447
    switch (sense) {
415 448
    case MIN:
416 449
      CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
417 450
      break;
418 451
    case MAX:
419 452
      CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
420 453
      break;
421 454
    }
422 455
  }
423 456

	
424 457
  CplexBase::Sense CplexBase::_getSense() const {
425 458
    switch (CPXgetobjsen(cplexEnv(), _prob)) {
426 459
    case CPX_MIN:
427 460
      return MIN;
428 461
    case CPX_MAX:
429 462
      return MAX;
430 463
    default:
431 464
      LEMON_ASSERT(false, "Invalid sense");
432 465
      return CplexBase::Sense();
433 466
    }
434 467
  }
435 468

	
436 469
  void CplexBase::_clear() {
437 470
    CPXfreeprob(cplexEnv(),&_prob);
438 471
    int status;
439 472
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
440 473
    rows.clear();
441 474
    cols.clear();
442 475
  }
443 476

	
444 477
  void CplexBase::_messageLevel(MessageLevel level) {
445 478
    switch (level) {
446 479
    case MESSAGE_NOTHING:
447 480
      _message_enabled = false;
448 481
      break;
449 482
    case MESSAGE_ERROR:
450 483
    case MESSAGE_WARNING:
451 484
    case MESSAGE_NORMAL:
452 485
    case MESSAGE_VERBOSE:
453 486
      _message_enabled = true;
454 487
      break;
455 488
    }
456 489
  }
457 490

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

	
463 496
  // CplexLp members
464 497

	
465 498
  CplexLp::CplexLp()
466 499
    : LpBase(), LpSolver(), CplexBase() {}
467 500

	
468 501
  CplexLp::CplexLp(const CplexEnv& env)
469 502
    : LpBase(), LpSolver(), CplexBase(env) {}
470 503

	
471 504
  CplexLp::CplexLp(const CplexLp& other)
472 505
    : LpBase(), LpSolver(), CplexBase(other) {}
473 506

	
474 507
  CplexLp::~CplexLp() {}
475 508

	
476 509
  CplexLp* CplexLp::newSolver() const { return new CplexLp; }
477 510
  CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
478 511

	
479 512
  const char* CplexLp::_solverName() const { return "CplexLp"; }
480 513

	
481 514
  void CplexLp::_clear_temporals() {
482 515
    _col_status.clear();
483 516
    _row_status.clear();
484 517
    _primal_ray.clear();
485 518
    _dual_ray.clear();
486 519
  }
487 520

	
488 521
  // The routine returns zero unless an error occurred during the
489 522
  // optimization. Examples of errors include exhausting available
490 523
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
491 524
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
492 525
  // user-specified CPLEX limit, or proving the model infeasible or
493 526
  // unbounded, are not considered errors. Note that a zero return
494 527
  // value does not necessarily mean that a solution exists. Use query
495 528
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
496 529
  // further information about the status of the optimization.
497 530
  CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
498 531
#if CPX_VERSION >= 800
499 532
    if (status == 0) {
500 533
      switch (CPXgetstat(cplexEnv(), _prob)) {
501 534
      case CPX_STAT_OPTIMAL:
502 535
      case CPX_STAT_INFEASIBLE:
503 536
      case CPX_STAT_UNBOUNDED:
504 537
        return SOLVED;
505 538
      default:
506 539
        return UNSOLVED;
507 540
      }
508 541
    } else {
509 542
      return UNSOLVED;
510 543
    }
511 544
#else
512 545
    if (status == 0) {
513 546
      //We want to exclude some cases
514 547
      switch (CPXgetstat(cplexEnv(), _prob)) {
515 548
      case CPX_OBJ_LIM:
516 549
      case CPX_IT_LIM_FEAS:
517 550
      case CPX_IT_LIM_INFEAS:
518 551
      case CPX_TIME_LIM_FEAS:
519 552
      case CPX_TIME_LIM_INFEAS:
520 553
        return UNSOLVED;
521 554
      default:
522 555
        return SOLVED;
523 556
      }
524 557
    } else {
525 558
      return UNSOLVED;
526 559
    }
527 560
#endif
528 561
  }
529 562

	
530 563
  CplexLp::SolveExitStatus CplexLp::_solve() {
531 564
    _clear_temporals();
532 565
    _applyMessageLevel();
533 566
    return convertStatus(CPXlpopt(cplexEnv(), _prob));
534 567
  }
535 568

	
536 569
  CplexLp::SolveExitStatus CplexLp::solvePrimal() {
537 570
    _clear_temporals();
538 571
    _applyMessageLevel();
539 572
    return convertStatus(CPXprimopt(cplexEnv(), _prob));
540 573
  }
541 574

	
542 575
  CplexLp::SolveExitStatus CplexLp::solveDual() {
543 576
    _clear_temporals();
544 577
    _applyMessageLevel();
545 578
    return convertStatus(CPXdualopt(cplexEnv(), _prob));
546 579
  }
547 580

	
548 581
  CplexLp::SolveExitStatus CplexLp::solveBarrier() {
549 582
    _clear_temporals();
550 583
    _applyMessageLevel();
551 584
    return convertStatus(CPXbaropt(cplexEnv(), _prob));
552 585
  }
553 586

	
554 587
  CplexLp::Value CplexLp::_getPrimal(int i) const {
555 588
    Value x;
556 589
    CPXgetx(cplexEnv(), _prob, &x, i, i);
557 590
    return x;
558 591
  }
559 592

	
560 593
  CplexLp::Value CplexLp::_getDual(int i) const {
561 594
    Value y;
562 595
    CPXgetpi(cplexEnv(), _prob, &y, i, i);
563 596
    return y;
564 597
  }
565 598

	
566 599
  CplexLp::Value CplexLp::_getPrimalValue() const {
567 600
    Value objval;
568 601
    CPXgetobjval(cplexEnv(), _prob, &objval);
569 602
    return objval;
570 603
  }
571 604

	
572 605
  CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
573 606
    if (_col_status.empty()) {
574 607
      _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
575 608
      CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
576 609
    }
577 610
    switch (_col_status[i]) {
578 611
    case CPX_BASIC:
579 612
      return BASIC;
580 613
    case CPX_FREE_SUPER:
581 614
      return FREE;
582 615
    case CPX_AT_LOWER:
583 616
      return LOWER;
584 617
    case CPX_AT_UPPER:
585 618
      return UPPER;
586 619
    default:
587 620
      LEMON_ASSERT(false, "Wrong column status");
588 621
      return CplexLp::VarStatus();
589 622
    }
590 623
  }
591 624

	
592 625
  CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
593 626
    if (_row_status.empty()) {
594 627
      _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
595 628
      CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
596 629
    }
597 630
    switch (_row_status[i]) {
598 631
    case CPX_BASIC:
599 632
      return BASIC;
600 633
    case CPX_AT_LOWER:
601 634
      {
602 635
        char s;
603 636
        CPXgetsense(cplexEnv(), _prob, &s, i, i);
604 637
        return s != 'L' ? LOWER : UPPER;
605 638
      }
606 639
    case CPX_AT_UPPER:
607 640
      return UPPER;
608 641
    default:
609 642
      LEMON_ASSERT(false, "Wrong row status");
610 643
      return CplexLp::VarStatus();
611 644
    }
612 645
  }
613 646

	
614 647
  CplexLp::Value CplexLp::_getPrimalRay(int i) const {
615 648
    if (_primal_ray.empty()) {
616 649
      _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
617 650
      CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
618 651
    }
619 652
    return _primal_ray[i];
620 653
  }
621 654

	
622 655
  CplexLp::Value CplexLp::_getDualRay(int i) const {
623 656
    if (_dual_ray.empty()) {
624 657

	
625 658
    }
Show white space 1024 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
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
96 97

	
97 98
    virtual void _eraseCol(int i);
98 99
    virtual void _eraseRow(int i);
99 100

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
145 146
    virtual void _clear();
146 147

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

	
150 151
    bool _message_enabled;
151 152

	
152 153
  public:
153 154

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

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

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

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

	
172 173
  };
173 174

	
174 175
  /// \brief Interface for the CPLEX LP solver
175 176
  ///
176 177
  /// This class implements an interface for the CPLEX LP solver.
177 178
  ///\ingroup lp_group
178 179
  class CplexLp : public LpSolver, public CplexBase {
179 180
  public:
180 181
    /// \e
181 182
    CplexLp();
182 183
    /// \e
183 184
    CplexLp(const CplexEnv&);
184 185
    /// \e
185 186
    CplexLp(const CplexLp&);
186 187
    /// \e
187 188
    virtual ~CplexLp();
188 189

	
189 190
    /// \e
190 191
    virtual CplexLp* cloneSolver() const;
191 192
    /// \e
192 193
    virtual CplexLp* newSolver() const;
193 194

	
194 195
  private:
195 196

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

	
200 201
    mutable std::vector<Value> _primal_ray;
201 202
    mutable std::vector<Value> _dual_ray;
202 203

	
203 204
    void _clear_temporals();
204 205

	
205 206
    SolveExitStatus convertStatus(int status);
206 207

	
207 208
  protected:
208 209

	
209 210
    virtual const char* _solverName() const;
210 211

	
211 212
    virtual SolveExitStatus _solve();
212 213
    virtual Value _getPrimal(int i) const;
213 214
    virtual Value _getDual(int i) const;
214 215
    virtual Value _getPrimalValue() const;
215 216

	
216 217
    virtual VarStatus _getColStatus(int i) const;
217 218
    virtual VarStatus _getRowStatus(int i) const;
218 219

	
219 220
    virtual Value _getPrimalRay(int i) const;
220 221
    virtual Value _getDualRay(int i) const;
221 222

	
222 223
    virtual ProblemType _getPrimalType() const;
223 224
    virtual ProblemType _getDualType() const;
224 225

	
225 226
  public:
226 227

	
227 228
    /// Solve with primal simplex method
228 229
    SolveExitStatus solvePrimal();
229 230

	
230 231
    /// Solve with dual simplex method
231 232
    SolveExitStatus solveDual();
232 233

	
233 234
    /// Solve with barrier method
234 235
    SolveExitStatus solveBarrier();
235 236

	
236 237
  };
237 238

	
238 239
  /// \brief Interface for the CPLEX MIP solver
239 240
  ///
240 241
  /// This class implements an interface for the CPLEX MIP solver.
241 242
  ///\ingroup lp_group
242 243
  class CplexMip : public MipSolver, public CplexBase {
243 244
  public:
244 245
    /// \e
245 246
    CplexMip();
246 247
    /// \e
247 248
    CplexMip(const CplexEnv&);
248 249
    /// \e
249 250
    CplexMip(const CplexMip&);
250 251
    /// \e
251 252
    virtual ~CplexMip();
252 253

	
253 254
    /// \e
254 255
    virtual CplexMip* cloneSolver() const;
255 256
    /// \e
256 257
    virtual CplexMip* newSolver() const;
257 258

	
258 259
  protected:
259 260

	
260 261

	
261 262
    virtual const char* _solverName() const;
262 263

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

	
266 267
    virtual SolveExitStatus _solve();
267 268
    virtual ProblemType _getType() const;
268 269
    virtual Value _getSol(int i) const;
269 270
    virtual Value _getSolValue() const;
270 271

	
271 272
  };
272 273

	
273 274
} //END OF NAMESPACE LEMON
274 275

	
275 276
#endif //LEMON_CPLEX_H
276 277

	
Show white space 1024 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 34
    messageLevel(MESSAGE_NOTHING);
35 35
  }
36 36

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

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

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

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

	
62
  int GlpkBase::_addRow(Value lo, ExprIterator b, 
63
                        ExprIterator e, Value up) {
64
    int i = glp_add_rows(lp, 1);
65

	
66
    if (lo == -INF) {
67
      if (up == INF) {
68
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
69
      } else {
70
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
71
      }    
72
    } else {
73
      if (up == INF) {
74
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
75
      } else if (lo != up) {        
76
        glp_set_row_bnds(lp, i, GLP_DB, lo, up);
77
      } else {
78
        glp_set_row_bnds(lp, i, GLP_FX, lo, up);
79
      }
80
    }
81

	
82
    std::vector<int> indexes;
83
    std::vector<Value> values;
84

	
85
    indexes.push_back(0);
86
    values.push_back(0);
87

	
88
    for(ExprIterator it = b; it != e; ++it) {
89
      indexes.push_back(it->first);
90
      values.push_back(it->second);
91
    }
92

	
93
    glp_set_mat_row(lp, i, values.size() - 1,
94
                    &indexes.front(), &values.front());
95
    return i;
96
  }
97

	
62 98
  void GlpkBase::_eraseCol(int i) {
63 99
    int ca[2];
64 100
    ca[1] = i;
65 101
    glp_del_cols(lp, 1, ca);
66 102
  }
67 103

	
68 104
  void GlpkBase::_eraseRow(int i) {
69 105
    int ra[2];
70 106
    ra[1] = i;
71 107
    glp_del_rows(lp, 1, ra);
72 108
  }
73 109

	
74 110
  void GlpkBase::_eraseColId(int i) {
75 111
    cols.eraseIndex(i);
76 112
    cols.shiftIndices(i);
77 113
  }
78 114

	
79 115
  void GlpkBase::_eraseRowId(int i) {
80 116
    rows.eraseIndex(i);
81 117
    rows.shiftIndices(i);
82 118
  }
83 119

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

	
90 126
  void GlpkBase::_setColName(int c, const std::string & name) {
91 127
    glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
92 128

	
93 129
  }
94 130

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

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

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

	
109 145
  }
110 146

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

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

	
120 156
    indexes.push_back(0);
121 157
    values.push_back(0);
122 158

	
123 159
    for(ExprIterator it = b; it != e; ++it) {
124 160
      indexes.push_back(it->first);
125 161
      values.push_back(it->second);
126 162
    }
127 163

	
128 164
    glp_set_mat_row(lp, i, values.size() - 1,
129 165
                    &indexes.front(), &values.front());
130 166
  }
131 167

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

	
135 171
    std::vector<int> indexes(length + 1);
136 172
    std::vector<Value> values(length + 1);
137 173

	
138 174
    glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
139 175

	
140 176
    for (int i = 1; i <= length; ++i) {
141 177
      *b = std::make_pair(indexes[i], values[i]);
142 178
      ++b;
143 179
    }
144 180
  }
145 181

	
146 182
  void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
147 183
                                     ExprIterator e) {
148 184

	
149 185
    std::vector<int> indexes;
150 186
    std::vector<Value> values;
151 187

	
152 188
    indexes.push_back(0);
153 189
    values.push_back(0);
154 190

	
155 191
    for(ExprIterator it = b; it != e; ++it) {
156 192
      indexes.push_back(it->first);
157 193
      values.push_back(it->second);
158 194
    }
159 195

	
160 196
    glp_set_mat_col(lp, ix, values.size() - 1,
161 197
                    &indexes.front(), &values.front());
162 198
  }
163 199

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

	
167 203
    std::vector<int> indexes(length + 1);
168 204
    std::vector<Value> values(length + 1);
169 205

	
170 206
    glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
171 207

	
172 208
    for (int i = 1; i  <= length; ++i) {
173 209
      *b = std::make_pair(indexes[i], values[i]);
174 210
      ++b;
175 211
    }
176 212
  }
177 213

	
178 214
  void GlpkBase::_setCoeff(int ix, int jx, Value value) {
179 215

	
180 216
    if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
181 217

	
182 218
      int length = glp_get_mat_row(lp, ix, 0, 0);
183 219

	
184 220
      std::vector<int> indexes(length + 2);
185 221
      std::vector<Value> values(length + 2);
186 222

	
187 223
      glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
188 224

	
189 225
      //The following code does not suppose that the elements of the
190 226
      //array indexes are sorted
191 227
      bool found = false;
192 228
      for (int i = 1; i  <= length; ++i) {
193 229
        if (indexes[i] == jx) {
194 230
          found = true;
195 231
          values[i] = value;
196 232
          break;
197 233
        }
198 234
      }
199 235
      if (!found) {
200 236
        ++length;
201 237
        indexes[length] = jx;
202 238
        values[length] = value;
203 239
      }
204 240

	
205 241
      glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
206 242

	
207 243
    } else {
208 244

	
209 245
      int length = glp_get_mat_col(lp, jx, 0, 0);
210 246

	
211 247
      std::vector<int> indexes(length + 2);
212 248
      std::vector<Value> values(length + 2);
213 249

	
214 250
      glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
215 251

	
216 252
      //The following code does not suppose that the elements of the
217 253
      //array indexes are sorted
218 254
      bool found = false;
219 255
      for (int i = 1; i <= length; ++i) {
220 256
        if (indexes[i] == ix) {
221 257
          found = true;
222 258
          values[i] = value;
223 259
          break;
224 260
        }
225 261
      }
226 262
      if (!found) {
227 263
        ++length;
228 264
        indexes[length] = ix;
229 265
        values[length] = value;
230 266
      }
231 267

	
232 268
      glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
233 269
    }
234 270

	
235 271
  }
236 272

	
237 273
  GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
238 274

	
239 275
    int length = glp_get_mat_row(lp, ix, 0, 0);
240 276

	
241 277
    std::vector<int> indexes(length + 1);
242 278
    std::vector<Value> values(length + 1);
243 279

	
244 280
    glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
245 281

	
246 282
    for (int i = 1; i  <= length; ++i) {
247 283
      if (indexes[i] == jx) {
248 284
        return values[i];
249 285
      }
250 286
    }
251 287

	
252 288
    return 0;
253 289
  }
254 290

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

	
258 294
    int b = glp_get_col_type(lp, i);
259 295
    double up = glp_get_col_ub(lp, i);
260 296
    if (lo == -INF) {
261 297
      switch (b) {
262 298
      case GLP_FR:
263 299
      case GLP_LO:
264 300
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
265 301
        break;
266 302
      case GLP_UP:
267 303
        break;
268 304
      case GLP_DB:
269 305
      case GLP_FX:
270 306
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
271 307
        break;
272 308
      default:
273 309
        break;
274 310
      }
275 311
    } else {
276 312
      switch (b) {
277 313
      case GLP_FR:
278 314
      case GLP_LO:
279 315
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
280 316
        break;
281 317
      case GLP_UP:
282 318
      case GLP_DB:
283 319
      case GLP_FX:
284 320
        if (lo == up)
285 321
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
286 322
        else
287 323
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
288 324
        break;
289 325
      default:
290 326
        break;
291 327
      }
292 328
    }
293 329
  }
294 330

	
295 331
  GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
296 332
    int b = glp_get_col_type(lp, i);
297 333
    switch (b) {
298 334
    case GLP_LO:
299 335
    case GLP_DB:
300 336
    case GLP_FX:
301 337
      return glp_get_col_lb(lp, i);
302 338
    default:
303 339
      return -INF;
304 340
    }
305 341
  }
306 342

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

	
310 346
    int b = glp_get_col_type(lp, i);
311 347
    double lo = glp_get_col_lb(lp, i);
312 348
    if (up == INF) {
313 349
      switch (b) {
314 350
      case GLP_FR:
315 351
      case GLP_LO:
316 352
        break;
317 353
      case GLP_UP:
318 354
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
319 355
        break;
320 356
      case GLP_DB:
321 357
      case GLP_FX:
322 358
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
323 359
        break;
324 360
      default:
325 361
        break;
326 362
      }
327 363
    } else {
328 364
      switch (b) {
329 365
      case GLP_FR:
330 366
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
331 367
        break;
332 368
      case GLP_UP:
333 369
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
334 370
        break;
335 371
      case GLP_LO:
336 372
      case GLP_DB:
337 373
      case GLP_FX:
338 374
        if (lo == up)
339 375
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
340 376
        else
341 377
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
342 378
        break;
343 379
      default:
344 380
        break;
345 381
      }
346 382
    }
347 383

	
348 384
  }
349 385

	
350 386
  GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
351 387
    int b = glp_get_col_type(lp, i);
352 388
      switch (b) {
353 389
      case GLP_UP:
354 390
      case GLP_DB:
355 391
      case GLP_FX:
356 392
        return glp_get_col_ub(lp, i);
357 393
      default:
358 394
        return INF;
359 395
      }
360 396
  }
361 397

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

	
365 401
    int b = glp_get_row_type(lp, i);
366 402
    double up = glp_get_row_ub(lp, i);
367 403
    if (lo == -INF) {
368 404
      switch (b) {
369 405
      case GLP_FR:
370 406
      case GLP_LO:
371 407
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
372 408
        break;
373 409
      case GLP_UP:
374 410
        break;
375 411
      case GLP_DB:
376 412
      case GLP_FX:
377 413
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
378 414
        break;
379 415
      default:
380 416
        break;
381 417
      }
382 418
    } else {
383 419
      switch (b) {
384 420
      case GLP_FR:
385 421
      case GLP_LO:
386 422
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
387 423
        break;
388 424
      case GLP_UP:
389 425
      case GLP_DB:
390 426
      case GLP_FX:
391 427
        if (lo == up)
392 428
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
393 429
        else
394 430
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
395 431
        break;
396 432
      default:
397 433
        break;
398 434
      }
399 435
    }
400 436

	
401 437
  }
402 438

	
403 439
  GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
404 440
    int b = glp_get_row_type(lp, i);
405 441
    switch (b) {
406 442
    case GLP_LO:
407 443
    case GLP_DB:
408 444
    case GLP_FX:
409 445
      return glp_get_row_lb(lp, i);
410 446
    default:
411 447
      return -INF;
412 448
    }
413 449
  }
414 450

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

	
418 454
    int b = glp_get_row_type(lp, i);
419 455
    double lo = glp_get_row_lb(lp, i);
420 456
    if (up == INF) {
421 457
      switch (b) {
422 458
      case GLP_FR:
423 459
      case GLP_LO:
424 460
        break;
425 461
      case GLP_UP:
426 462
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
427 463
        break;
428 464
      case GLP_DB:
429 465
      case GLP_FX:
430 466
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
431 467
        break;
432 468
      default:
433 469
        break;
434 470
      }
435 471
    } else {
436 472
      switch (b) {
437 473
      case GLP_FR:
438 474
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
439 475
        break;
440 476
      case GLP_UP:
441 477
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
442 478
        break;
443 479
      case GLP_LO:
444 480
      case GLP_DB:
445 481
      case GLP_FX:
446 482
        if (lo == up)
447 483
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
448 484
        else
449 485
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
450 486
        break;
451 487
      default:
452 488
        break;
453 489
      }
454 490
    }
455 491
  }
456 492

	
457 493
  GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
458 494
    int b = glp_get_row_type(lp, i);
459 495
    switch (b) {
460 496
    case GLP_UP:
461 497
    case GLP_DB:
462 498
    case GLP_FX:
463 499
      return glp_get_row_ub(lp, i);
464 500
    default:
465 501
      return INF;
466 502
    }
467 503
  }
468 504

	
469 505
  void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
470 506
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
471 507
      glp_set_obj_coef(lp, i, 0.0);
472 508
    }
473 509
    for (ExprIterator it = b; it != e; ++it) {
474 510
      glp_set_obj_coef(lp, it->first, it->second);
475 511
    }
476 512
  }
477 513

	
478 514
  void GlpkBase::_getObjCoeffs(InsertIterator b) const {
479 515
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
480 516
      Value val = glp_get_obj_coef(lp, i);
481 517
      if (val != 0.0) {
482 518
        *b = std::make_pair(i, val);
483 519
        ++b;
484 520
      }
485 521
    }
486 522
  }
487 523

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

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

	
498 534
  void GlpkBase::_setSense(GlpkBase::Sense sense) {
499 535
    switch (sense) {
500 536
    case MIN:
501 537
      glp_set_obj_dir(lp, GLP_MIN);
502 538
      break;
503 539
    case MAX:
504 540
      glp_set_obj_dir(lp, GLP_MAX);
505 541
      break;
506 542
    }
507 543
  }
508 544

	
509 545
  GlpkBase::Sense GlpkBase::_getSense() const {
510 546
    switch(glp_get_obj_dir(lp)) {
511 547
    case GLP_MIN:
512 548
      return MIN;
513 549
    case GLP_MAX:
514 550
      return MAX;
515 551
    default:
516 552
      LEMON_ASSERT(false, "Wrong sense");
517 553
      return GlpkBase::Sense();
518 554
    }
519 555
  }
520 556

	
521 557
  void GlpkBase::_clear() {
522 558
    glp_erase_prob(lp);
523 559
    rows.clear();
524 560
    cols.clear();
525 561
  }
526 562

	
527 563
  void GlpkBase::freeEnv() {
528 564
    glp_free_env();
529 565
  }
530 566

	
531 567
  void GlpkBase::_messageLevel(MessageLevel level) {
532 568
    switch (level) {
533 569
    case MESSAGE_NOTHING:
534 570
      _message_level = GLP_MSG_OFF;
535 571
      break;
536 572
    case MESSAGE_ERROR:
537 573
      _message_level = GLP_MSG_ERR;
538 574
      break;
539 575
    case MESSAGE_WARNING:
540 576
      _message_level = GLP_MSG_ERR;
541 577
      break;
542 578
    case MESSAGE_NORMAL:
543 579
      _message_level = GLP_MSG_ON;
544 580
      break;
545 581
    case MESSAGE_VERBOSE:
546 582
      _message_level = GLP_MSG_ALL;
547 583
      break;
548 584
    }
549 585
  }
550 586

	
551 587
  GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
552 588

	
553 589
  // GlpkLp members
554 590

	
555 591
  GlpkLp::GlpkLp()
556 592
    : LpBase(), LpSolver(), GlpkBase() {
557 593
    presolver(false);
558 594
  }
559 595

	
560 596
  GlpkLp::GlpkLp(const GlpkLp& other)
561 597
    : LpBase(other), LpSolver(other), GlpkBase(other) {
562 598
    presolver(false);
563 599
  }
564 600

	
565 601
  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
566 602
  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
567 603

	
568 604
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
569 605

	
570 606
  void GlpkLp::_clear_temporals() {
571 607
    _primal_ray.clear();
572 608
    _dual_ray.clear();
573 609
  }
Show white space 1024 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
#if !defined _GLP_PROB && !defined GLP_PROB
30 30
#define _GLP_PROB
31 31
#define GLP_PROB
32 32
typedef struct { double _opaque_prob; } glp_prob;
33 33
/* LP/MIP problem object */
34 34
#endif
35 35

	
36 36
namespace lemon {
37 37

	
38 38

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

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

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

	
53 53
  protected:
54 54

	
55 55
    virtual int _addCol();
56 56
    virtual int _addRow();
57
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
57 58

	
58 59
    virtual void _eraseCol(int i);
59 60
    virtual void _eraseRow(int i);
60 61

	
61 62
    virtual void _eraseColId(int i);
62 63
    virtual void _eraseRowId(int i);
63 64

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

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

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

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

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

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

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

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

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

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

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

	
99 100
    virtual void _setSense(Sense);
100 101
    virtual Sense _getSense() const;
101 102

	
102 103
    virtual void _clear();
103 104

	
104 105
    virtual void _messageLevel(MessageLevel level);
105 106

	
106 107
  private:
107 108

	
108 109
    static void freeEnv();
109 110

	
110 111
    struct FreeEnvHelper {
111 112
      ~FreeEnvHelper() {
112 113
        freeEnv();
113 114
      }
114 115
    };
115 116
    
116 117
    static FreeEnvHelper freeEnvHelper;
117 118

	
118 119
  protected:
119 120
    
120 121
    int _message_level;
121 122
    
122 123
  public:
123 124

	
124 125
    ///Pointer to the underlying GLPK data structure.
125 126
    LPX *lpx() {return lp;}
126 127
    ///Const pointer to the underlying GLPK data structure.
127 128
    const LPX *lpx() const {return lp;}
128 129

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

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

	
135 136
  };
136 137

	
137 138
  /// \brief Interface for the GLPK LP solver
138 139
  ///
139 140
  /// This class implements an interface for the GLPK LP solver.
140 141
  ///\ingroup lp_group
141 142
  class GlpkLp : public LpSolver, public GlpkBase {
142 143
  public:
143 144

	
144 145
    ///\e
145 146
    GlpkLp();
146 147
    ///\e
147 148
    GlpkLp(const GlpkLp&);
148 149

	
149 150
    ///\e
150 151
    virtual GlpkLp* cloneSolver() const;
151 152
    ///\e
152 153
    virtual GlpkLp* newSolver() const;
153 154

	
154 155
  private:
155 156

	
156 157
    mutable std::vector<double> _primal_ray;
157 158
    mutable std::vector<double> _dual_ray;
158 159

	
159 160
    void _clear_temporals();
160 161

	
161 162
  protected:
162 163

	
163 164
    virtual const char* _solverName() const;
164 165

	
165 166
    virtual SolveExitStatus _solve();
166 167
    virtual Value _getPrimal(int i) const;
167 168
    virtual Value _getDual(int i) const;
168 169

	
169 170
    virtual Value _getPrimalValue() const;
170 171

	
171 172
    virtual VarStatus _getColStatus(int i) const;
172 173
    virtual VarStatus _getRowStatus(int i) const;
173 174

	
174 175
    virtual Value _getPrimalRay(int i) const;
175 176
    virtual Value _getDualRay(int i) const;
176 177

	
177 178
    virtual ProblemType _getPrimalType() const;
178 179
    virtual ProblemType _getDualType() const;
179 180

	
180 181
  public:
181 182

	
182 183
    ///Solve with primal simplex
183 184
    SolveExitStatus solvePrimal();
184 185

	
185 186
    ///Solve with dual simplex
186 187
    SolveExitStatus solveDual();
187 188

	
188 189
  private:
189 190

	
190 191
    bool _presolve;
191 192

	
192 193
  public:
193 194

	
194 195
    ///Turns on or off the presolver
195 196

	
196 197
    ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
197 198
    ///
198 199
    ///The presolver is off by default.
199 200
    void presolver(bool presolve);
200 201

	
201 202
  };
202 203

	
203 204
  /// \brief Interface for the GLPK MIP solver
204 205
  ///
205 206
  /// This class implements an interface for the GLPK MIP solver.
206 207
  ///\ingroup lp_group
207 208
  class GlpkMip : public MipSolver, public GlpkBase {
208 209
  public:
209 210

	
210 211
    ///\e
211 212
    GlpkMip();
212 213
    ///\e
213 214
    GlpkMip(const GlpkMip&);
214 215

	
215 216
    virtual GlpkMip* cloneSolver() const;
216 217
    virtual GlpkMip* newSolver() const;
217 218

	
218 219
  protected:
219 220

	
220 221
    virtual const char* _solverName() const;
221 222

	
222 223
    virtual ColTypes _getColType(int col) const;
223 224
    virtual void _setColType(int col, ColTypes col_type);
224 225

	
225 226
    virtual SolveExitStatus _solve();
226 227
    virtual ProblemType _getType() const;
227 228
    virtual Value _getSol(int i) const;
228 229
    virtual Value _getSolValue() const;
229 230

	
230 231
  };
231 232

	
232 233

	
233 234
} //END OF NAMESPACE LEMON
234 235

	
235 236
#endif //LEMON_GLPK_H
236 237

	
Show white space 1024 line context
... ...
@@ -434,1300 +434,1314 @@
434 434
      Expr &operator*=(const Value &v) {
435 435
        for (std::map<int, Value>::iterator it=comps.begin();
436 436
             it!=comps.end(); ++it)
437 437
          it->second*=v;
438 438
        const_comp*=v;
439 439
        return *this;
440 440
      }
441 441
      ///Division with a constant
442 442
      Expr &operator/=(const Value &c) {
443 443
        for (std::map<int, Value>::iterator it=comps.begin();
444 444
             it!=comps.end(); ++it)
445 445
          it->second/=c;
446 446
        const_comp/=c;
447 447
        return *this;
448 448
      }
449 449

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

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

	
464 464
      public:
465 465

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

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

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

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

	
489 489
        /// Equality operator
490 490
        bool operator==(Invalid) const { return _it == _end; }
491 491
        /// Inequality operator
492 492
        bool operator!=(Invalid) const { return _it != _end; }
493 493
      };
494 494

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

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

	
509 509
      public:
510 510

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

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

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

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

	
532 532
        /// Equality operator
533 533
        bool operator==(Invalid) const { return _it == _end; }
534 534
        /// Inequality operator
535 535
        bool operator!=(Invalid) const { return _it != _end; }
536 536
      };
537 537

	
538 538
    };
539 539

	
540 540
    ///Linear constraint
541 541

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

	
573 573
    protected:
574 574
      Expr _expr;
575 575
      Value _lb,_ub;
576 576
    public:
577 577
      ///\e
578 578
      Constr() : _expr(), _lb(NaN), _ub(NaN) {}
579 579
      ///\e
580 580
      Constr(Value lb, const Expr &e, Value ub) :
581 581
        _expr(e), _lb(lb), _ub(ub) {}
582 582
      Constr(const Expr &e) :
583 583
        _expr(e), _lb(NaN), _ub(NaN) {}
584 584
      ///\e
585 585
      void clear()
586 586
      {
587 587
        _expr.clear();
588 588
        _lb=_ub=NaN;
589 589
      }
590 590

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

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

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

	
622 622
    };
623 623

	
624 624
    ///Linear expression of rows
625 625

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

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

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

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

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

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

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

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

	
773 773
      public:
774 774

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

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

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

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

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

	
799 799
        /// Equality operator
800 800
        bool operator==(Invalid) const { return _it == _end; }
801 801
        /// Inequality operator
802 802
        bool operator!=(Invalid) const { return _it != _end; }
803 803
      };
804 804

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

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

	
819 819
      public:
820 820

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

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

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

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

	
842 842
        /// Equality operator
843 843
        bool operator==(Invalid) const { return _it == _end; }
844 844
        /// Inequality operator
845 845
        bool operator!=(Invalid) const { return _it != _end; }
846 846
      };
847 847
    };
848 848

	
849 849

	
850 850
  protected:
851 851

	
852 852
    class InsertIterator {
853 853
    private:
854 854

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

	
858 858
    public:
859 859

	
860 860
      typedef std::output_iterator_tag iterator_category;
861 861
      typedef void difference_type;
862 862
      typedef void value_type;
863 863
      typedef void reference;
864 864
      typedef void pointer;
865 865

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

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

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

	
880 880
    };
881 881

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

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

	
893 893
      class pointer {
894 894
      public:
895 895
        pointer(value_type& _value) : value(_value) {}
896 896
        value_type* operator->() { return &value; }
897 897
      private:
898 898
        value_type value;
899 899
      };
900 900

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

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

	
909 909
      pointer operator->() {
910 910
        return pointer(operator*());
911 911
      }
912 912

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

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

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

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

	
931 931
    };
932 932

	
933 933
  protected:
934 934

	
935 935
    //Abstract virtual functions
936 936

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

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

	
943 943
    virtual int _addCol() = 0;
944 944
    virtual int _addRow() = 0;
945 945

	
946
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
947
      int row = _addRow();
948
      _setRowCoeffs(row, b, e);
949
      _setRowLowerBound(row, l);
950
      _setRowUpperBound(row, u);
951
      return row;
952
    }
953

	
946 954
    virtual void _eraseCol(int col) = 0;
947 955
    virtual void _eraseRow(int row) = 0;
948 956

	
949 957
    virtual void _getColName(int col, std::string& name) const = 0;
950 958
    virtual void _setColName(int col, const std::string& name) = 0;
951 959
    virtual int _colByName(const std::string& name) const = 0;
952 960

	
953 961
    virtual void _getRowName(int row, std::string& name) const = 0;
954 962
    virtual void _setRowName(int row, const std::string& name) = 0;
955 963
    virtual int _rowByName(const std::string& name) const = 0;
956 964

	
957 965
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
958 966
    virtual void _getRowCoeffs(int i, InsertIterator b) const = 0;
959 967

	
960 968
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
961 969
    virtual void _getColCoeffs(int i, InsertIterator b) const = 0;
962 970

	
963 971
    virtual void _setCoeff(int row, int col, Value value) = 0;
964 972
    virtual Value _getCoeff(int row, int col) const = 0;
965 973

	
966 974
    virtual void _setColLowerBound(int i, Value value) = 0;
967 975
    virtual Value _getColLowerBound(int i) const = 0;
968 976

	
969 977
    virtual void _setColUpperBound(int i, Value value) = 0;
970 978
    virtual Value _getColUpperBound(int i) const = 0;
971 979

	
972 980
    virtual void _setRowLowerBound(int i, Value value) = 0;
973 981
    virtual Value _getRowLowerBound(int i) const = 0;
974 982

	
975 983
    virtual void _setRowUpperBound(int i, Value value) = 0;
976 984
    virtual Value _getRowUpperBound(int i) const = 0;
977 985

	
978 986
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e) = 0;
979 987
    virtual void _getObjCoeffs(InsertIterator b) const = 0;
980 988

	
981 989
    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
982 990
    virtual Value _getObjCoeff(int i) const = 0;
983 991

	
984 992
    virtual void _setSense(Sense) = 0;
985 993
    virtual Sense _getSense() const = 0;
986 994

	
987 995
    virtual void _clear() = 0;
988 996

	
989 997
    virtual const char* _solverName() const = 0;
990 998

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

	
993 1001
    //Own protected stuff
994 1002

	
995 1003
    //Constant component of the objective function
996 1004
    Value obj_const_comp;
997 1005

	
998 1006
    LpBase() : rows(), cols(), obj_const_comp(0) {}
999 1007

	
1000 1008
  public:
1001 1009

	
1002 1010
    /// Virtual destructor
1003 1011
    virtual ~LpBase() {}
1004 1012

	
1005 1013
    ///Gives back the name of the solver.
1006 1014
    const char* solverName() const {return _solverName();}
1007 1015

	
1008 1016
    ///\name Build Up and Modify the LP
1009 1017

	
1010 1018
    ///@{
1011 1019

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

	
1015 1023
    ///\brief Adds several new columns (i.e variables) at once
1016 1024
    ///
1017 1025
    ///This magic function takes a container as its argument and fills
1018 1026
    ///its elements with new columns (i.e. variables)
1019 1027
    ///\param t can be
1020 1028
    ///- a standard STL compatible iterable container with
1021 1029
    ///\ref Col as its \c values_type like
1022 1030
    ///\code
1023 1031
    ///std::vector<LpBase::Col>
1024 1032
    ///std::list<LpBase::Col>
1025 1033
    ///\endcode
1026 1034
    ///- a standard STL compatible iterable container with
1027 1035
    ///\ref Col as its \c mapped_type like
1028 1036
    ///\code
1029 1037
    ///std::map<AnyType,LpBase::Col>
1030 1038
    ///\endcode
1031 1039
    ///- an iterable lemon \ref concepts::WriteMap "write map" like
1032 1040
    ///\code
1033 1041
    ///ListGraph::NodeMap<LpBase::Col>
1034 1042
    ///ListGraph::ArcMap<LpBase::Col>
1035 1043
    ///\endcode
1036 1044
    ///\return The number of the created column.
1037 1045
#ifdef DOXYGEN
1038 1046
    template<class T>
1039 1047
    int addColSet(T &t) { return 0;}
1040 1048
#else
1041 1049
    template<class T>
1042 1050
    typename enable_if<typename T::value_type::LpCol,int>::type
1043 1051
    addColSet(T &t,dummy<0> = 0) {
1044 1052
      int s=0;
1045 1053
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
1046 1054
      return s;
1047 1055
    }
1048 1056
    template<class T>
1049 1057
    typename enable_if<typename T::value_type::second_type::LpCol,
1050 1058
                       int>::type
1051 1059
    addColSet(T &t,dummy<1> = 1) {
1052 1060
      int s=0;
1053 1061
      for(typename T::iterator i=t.begin();i!=t.end();++i) {
1054 1062
        i->second=addCol();
1055 1063
        s++;
1056 1064
      }
1057 1065
      return s;
1058 1066
    }
1059 1067
    template<class T>
1060 1068
    typename enable_if<typename T::MapIt::Value::LpCol,
1061 1069
                       int>::type
1062 1070
    addColSet(T &t,dummy<2> = 2) {
1063 1071
      int s=0;
1064 1072
      for(typename T::MapIt i(t); i!=INVALID; ++i)
1065 1073
        {
1066 1074
          i.set(addCol());
1067 1075
          s++;
1068 1076
        }
1069 1077
      return s;
1070 1078
    }
1071 1079
#endif
1072 1080

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

	
1075 1083
    ///\param c is the column to be modified
1076 1084
    ///\param e is a dual linear expression (see \ref DualExpr)
1077 1085
    ///a better one.
1078 1086
    void col(Col c, const DualExpr &e) {
1079 1087
      e.simplify();
1080 1088
      _setColCoeffs(cols(id(c)), ExprIterator(e.comps.begin(), rows),
1081 1089
                    ExprIterator(e.comps.end(), rows));
1082 1090
    }
1083 1091

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

	
1086 1094
    ///\param c is the column to get
1087 1095
    ///\return the dual expression associated to the column
1088 1096
    DualExpr col(Col c) const {
1089 1097
      DualExpr e;
1090 1098
      _getColCoeffs(cols(id(c)), InsertIterator(e.comps, rows));
1091 1099
      return e;
1092 1100
    }
1093 1101

	
1094 1102
    ///Add a new column to the LP
1095 1103

	
1096 1104
    ///\param e is a dual linear expression (see \ref DualExpr)
1097 1105
    ///\param o is the corresponding component of the objective
1098 1106
    ///function. It is 0 by default.
1099 1107
    ///\return The created column.
1100 1108
    Col addCol(const DualExpr &e, Value o = 0) {
1101 1109
      Col c=addCol();
1102 1110
      col(c,e);
1103 1111
      objCoeff(c,o);
1104 1112
      return c;
1105 1113
    }
1106 1114

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

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

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

	
1169 1177
    ///Set a row (i.e a constraint) of the LP
1170 1178

	
1171 1179
    ///\param r is the row to be modified
1172 1180
    ///\param l is lower bound (-\ref INF means no bound)
1173 1181
    ///\param e is a linear expression (see \ref Expr)
1174 1182
    ///\param u is the upper bound (\ref INF means no bound)
1175 1183
    void row(Row r, Value l, const Expr &e, Value u) {
1176 1184
      e.simplify();
1177 1185
      _setRowCoeffs(rows(id(r)), ExprIterator(e.comps.begin(), cols),
1178 1186
                    ExprIterator(e.comps.end(), cols));
1179 1187
      _setRowLowerBound(rows(id(r)),l - *e);
1180 1188
      _setRowUpperBound(rows(id(r)),u - *e);
1181 1189
    }
1182 1190

	
1183 1191
    ///Set a row (i.e a constraint) of the LP
1184 1192

	
1185 1193
    ///\param r is the row to be modified
1186 1194
    ///\param c is a linear expression (see \ref Constr)
1187 1195
    void row(Row r, const Constr &c) {
1188 1196
      row(r, c.lowerBounded()?c.lowerBound():-INF,
1189 1197
          c.expr(), c.upperBounded()?c.upperBound():INF);
1190 1198
    }
1191 1199

	
1192 1200

	
1193 1201
    ///Get a row (i.e a constraint) of the LP
1194 1202

	
1195 1203
    ///\param r is the row to get
1196 1204
    ///\return the expression associated to the row
1197 1205
    Expr row(Row r) const {
1198 1206
      Expr e;
1199 1207
      _getRowCoeffs(rows(id(r)), InsertIterator(e.comps, cols));
1200 1208
      return e;
1201 1209
    }
1202 1210

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

	
1205 1213
    ///\param l is the lower bound (-\ref INF means no bound)
1206 1214
    ///\param e is a linear expression (see \ref Expr)
1207 1215
    ///\param u is the upper bound (\ref INF means no bound)
1208 1216
    ///\return The created row.
1209 1217
    Row addRow(Value l,const Expr &e, Value u) {
1210
      Row r=addRow();
1211
      row(r,l,e,u);
1218
      Row r;
1219
      e.simplify();
1220
      r._id = _addRowId(_addRow(l - *e, ExprIterator(e.comps.begin(), cols),
1221
                                ExprIterator(e.comps.end(), cols), u - *e));
1212 1222
      return r;
1213 1223
    }
1214 1224

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

	
1217 1227
    ///\param c is a linear expression (see \ref Constr)
1218 1228
    ///\return The created row.
1219 1229
    Row addRow(const Constr &c) {
1220
      Row r=addRow();
1221
      row(r,c);
1230
      Row r;
1231
      c.expr().simplify();
1232
      r._id = _addRowId(_addRow(c.lowerBounded()?c.lowerBound():-INF, 
1233
                                ExprIterator(c.expr().comps.begin(), cols),
1234
                                ExprIterator(c.expr().comps.end(), cols),
1235
                                c.upperBounded()?c.upperBound():INF));
1222 1236
      return r;
1223 1237
    }
1224 1238
    ///Erase a column (i.e a variable) from the LP
1225 1239

	
1226 1240
    ///\param c is the column to be deleted
1227 1241
    void erase(Col c) {
1228 1242
      _eraseCol(cols(id(c)));
1229 1243
      _eraseColId(cols(id(c)));
1230 1244
    }
1231 1245
    ///Erase a row (i.e a constraint) from the LP
1232 1246

	
1233 1247
    ///\param r is the row to be deleted
1234 1248
    void erase(Row r) {
1235 1249
      _eraseRow(rows(id(r)));
1236 1250
      _eraseRowId(rows(id(r)));
1237 1251
    }
1238 1252

	
1239 1253
    /// Get the name of a column
1240 1254

	
1241 1255
    ///\param c is the coresponding column
1242 1256
    ///\return The name of the colunm
1243 1257
    std::string colName(Col c) const {
1244 1258
      std::string name;
1245 1259
      _getColName(cols(id(c)), name);
1246 1260
      return name;
1247 1261
    }
1248 1262

	
1249 1263
    /// Set the name of a column
1250 1264

	
1251 1265
    ///\param c is the coresponding column
1252 1266
    ///\param name The name to be given
1253 1267
    void colName(Col c, const std::string& name) {
1254 1268
      _setColName(cols(id(c)), name);
1255 1269
    }
1256 1270

	
1257 1271
    /// Get the column by its name
1258 1272

	
1259 1273
    ///\param name The name of the column
1260 1274
    ///\return the proper column or \c INVALID
1261 1275
    Col colByName(const std::string& name) const {
1262 1276
      int k = _colByName(name);
1263 1277
      return k != -1 ? Col(cols[k]) : Col(INVALID);
1264 1278
    }
1265 1279

	
1266 1280
    /// Get the name of a row
1267 1281

	
1268 1282
    ///\param r is the coresponding row
1269 1283
    ///\return The name of the row
1270 1284
    std::string rowName(Row r) const {
1271 1285
      std::string name;
1272 1286
      _getRowName(rows(id(r)), name);
1273 1287
      return name;
1274 1288
    }
1275 1289

	
1276 1290
    /// Set the name of a row
1277 1291

	
1278 1292
    ///\param r is the coresponding row
1279 1293
    ///\param name The name to be given
1280 1294
    void rowName(Row r, const std::string& name) {
1281 1295
      _setRowName(rows(id(r)), name);
1282 1296
    }
1283 1297

	
1284 1298
    /// Get the row by its name
1285 1299

	
1286 1300
    ///\param name The name of the row
1287 1301
    ///\return the proper row or \c INVALID
1288 1302
    Row rowByName(const std::string& name) const {
1289 1303
      int k = _rowByName(name);
1290 1304
      return k != -1 ? Row(rows[k]) : Row(INVALID);
1291 1305
    }
1292 1306

	
1293 1307
    /// Set an element of the coefficient matrix of the LP
1294 1308

	
1295 1309
    ///\param r is the row of the element to be modified
1296 1310
    ///\param c is the column of the element to be modified
1297 1311
    ///\param val is the new value of the coefficient
1298 1312
    void coeff(Row r, Col c, Value val) {
1299 1313
      _setCoeff(rows(id(r)),cols(id(c)), val);
1300 1314
    }
1301 1315

	
1302 1316
    /// Get an element of the coefficient matrix of the LP
1303 1317

	
1304 1318
    ///\param r is the row of the element
1305 1319
    ///\param c is the column of the element
1306 1320
    ///\return the corresponding coefficient
1307 1321
    Value coeff(Row r, Col c) const {
1308 1322
      return _getCoeff(rows(id(r)),cols(id(c)));
1309 1323
    }
1310 1324

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

	
1313 1327
    /// The lower bound of a variable (column) has to be given by an
1314 1328
    /// extended number of type Value, i.e. a finite number of type
1315 1329
    /// Value or -\ref INF.
1316 1330
    void colLowerBound(Col c, Value value) {
1317 1331
      _setColLowerBound(cols(id(c)),value);
1318 1332
    }
1319 1333

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

	
1322 1336
    /// This function returns the lower bound for column (variable) \c c
1323 1337
    /// (this might be -\ref INF as well).
1324 1338
    ///\return The lower bound for column \c c
1325 1339
    Value colLowerBound(Col c) const {
1326 1340
      return _getColLowerBound(cols(id(c)));
1327 1341
    }
1328 1342

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

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

	
1368 1382
    /// The upper bound of a variable (column) has to be given by an
1369 1383
    /// extended number of type Value, i.e. a finite number of type
1370 1384
    /// Value or \ref INF.
1371 1385
    void colUpperBound(Col c, Value value) {
1372 1386
      _setColUpperBound(cols(id(c)),value);
1373 1387
    };
1374 1388

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

	
1377 1391
    /// This function returns the upper bound for column (variable) \c c
1378 1392
    /// (this might be \ref INF as well).
1379 1393
    /// \return The upper bound for column \c c
1380 1394
    Value colUpperBound(Col c) const {
1381 1395
      return _getColUpperBound(cols(id(c)));
1382 1396
    }
1383 1397

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

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

	
1423 1437
    /// The lower and the upper bounds of
1424 1438
    /// a variable (column) have to be given by an
1425 1439
    /// extended number of type Value, i.e. a finite number of type
1426 1440
    /// Value, -\ref INF or \ref INF.
1427 1441
    void colBounds(Col c, Value lower, Value upper) {
1428 1442
      _setColLowerBound(cols(id(c)),lower);
1429 1443
      _setColUpperBound(cols(id(c)),upper);
1430 1444
    }
1431 1445

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

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

	
1470 1484
    /// The lower bound of a constraint (row) has to be given by an
1471 1485
    /// extended number of type Value, i.e. a finite number of type
1472 1486
    /// Value or -\ref INF.
1473 1487
    void rowLowerBound(Row r, Value value) {
1474 1488
      _setRowLowerBound(rows(id(r)),value);
1475 1489
    }
1476 1490

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

	
1479 1493
    /// This function returns the lower bound for row (constraint) \c c
1480 1494
    /// (this might be -\ref INF as well).
1481 1495
    ///\return The lower bound for row \c r
1482 1496
    Value rowLowerBound(Row r) const {
1483 1497
      return _getRowLowerBound(rows(id(r)));
1484 1498
    }
1485 1499

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

	
1488 1502
    /// The upper bound of a constraint (row) has to be given by an
1489 1503
    /// extended number of type Value, i.e. a finite number of type
1490 1504
    /// Value or -\ref INF.
1491 1505
    void rowUpperBound(Row r, Value value) {
1492 1506
      _setRowUpperBound(rows(id(r)),value);
1493 1507
    }
1494 1508

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

	
1497 1511
    /// This function returns the upper bound for row (constraint) \c c
1498 1512
    /// (this might be -\ref INF as well).
1499 1513
    ///\return The upper bound for row \c r
1500 1514
    Value rowUpperBound(Row r) const {
1501 1515
      return _getRowUpperBound(rows(id(r)));
1502 1516
    }
1503 1517

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

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

	
1510 1524
    ///Set the objective function
1511 1525

	
1512 1526
    ///\param e is a linear expression of type \ref Expr.
1513 1527
    ///
1514 1528
    void obj(const Expr& e) {
1515 1529
      _setObjCoeffs(ExprIterator(e.comps.begin(), cols),
1516 1530
                    ExprIterator(e.comps.end(), cols));
1517 1531
      obj_const_comp = *e;
1518 1532
    }
1519 1533

	
1520 1534
    ///Get the objective function
1521 1535

	
1522 1536
    ///\return the objective function as a linear expression of type
1523 1537
    ///Expr.
1524 1538
    Expr obj() const {
1525 1539
      Expr e;
1526 1540
      _getObjCoeffs(InsertIterator(e.comps, cols));
1527 1541
      *e = obj_const_comp;
1528 1542
      return e;
1529 1543
    }
1530 1544

	
1531 1545

	
1532 1546
    ///Set the direction of optimization
1533 1547
    void sense(Sense sense) { _setSense(sense); }
1534 1548

	
1535 1549
    ///Query the direction of the optimization
1536 1550
    Sense sense() const {return _getSense(); }
1537 1551

	
1538 1552
    ///Set the sense to maximization
1539 1553
    void max() { _setSense(MAX); }
1540 1554

	
1541 1555
    ///Set the sense to maximization
1542 1556
    void min() { _setSense(MIN); }
1543 1557

	
1544 1558
    ///Clears the problem
1545 1559
    void clear() { _clear(); }
1546 1560

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

	
1550 1564
    ///@}
1551 1565

	
1552 1566
  };
1553 1567

	
1554 1568
  /// Addition
1555 1569

	
1556 1570
  ///\relates LpBase::Expr
1557 1571
  ///
1558 1572
  inline LpBase::Expr operator+(const LpBase::Expr &a, const LpBase::Expr &b) {
1559 1573
    LpBase::Expr tmp(a);
1560 1574
    tmp+=b;
1561 1575
    return tmp;
1562 1576
  }
1563 1577
  ///Substraction
1564 1578

	
1565 1579
  ///\relates LpBase::Expr
1566 1580
  ///
1567 1581
  inline LpBase::Expr operator-(const LpBase::Expr &a, const LpBase::Expr &b) {
1568 1582
    LpBase::Expr tmp(a);
1569 1583
    tmp-=b;
1570 1584
    return tmp;
1571 1585
  }
1572 1586
  ///Multiply with constant
1573 1587

	
1574 1588
  ///\relates LpBase::Expr
1575 1589
  ///
1576 1590
  inline LpBase::Expr operator*(const LpBase::Expr &a, const LpBase::Value &b) {
1577 1591
    LpBase::Expr tmp(a);
1578 1592
    tmp*=b;
1579 1593
    return tmp;
1580 1594
  }
1581 1595

	
1582 1596
  ///Multiply with constant
1583 1597

	
1584 1598
  ///\relates LpBase::Expr
1585 1599
  ///
1586 1600
  inline LpBase::Expr operator*(const LpBase::Value &a, const LpBase::Expr &b) {
1587 1601
    LpBase::Expr tmp(b);
1588 1602
    tmp*=a;
1589 1603
    return tmp;
1590 1604
  }
1591 1605
  ///Divide with constant
1592 1606

	
1593 1607
  ///\relates LpBase::Expr
1594 1608
  ///
1595 1609
  inline LpBase::Expr operator/(const LpBase::Expr &a, const LpBase::Value &b) {
1596 1610
    LpBase::Expr tmp(a);
1597 1611
    tmp/=b;
1598 1612
    return tmp;
1599 1613
  }
1600 1614

	
1601 1615
  ///Create constraint
1602 1616

	
1603 1617
  ///\relates LpBase::Constr
1604 1618
  ///
1605 1619
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1606 1620
                                   const LpBase::Expr &f) {
1607 1621
    return LpBase::Constr(0, f - e, LpBase::INF);
1608 1622
  }
1609 1623

	
1610 1624
  ///Create constraint
1611 1625

	
1612 1626
  ///\relates LpBase::Constr
1613 1627
  ///
1614 1628
  inline LpBase::Constr operator<=(const LpBase::Value &e,
1615 1629
                                   const LpBase::Expr &f) {
1616 1630
    return LpBase::Constr(e, f, LpBase::NaN);
1617 1631
  }
1618 1632

	
1619 1633
  ///Create constraint
1620 1634

	
1621 1635
  ///\relates LpBase::Constr
1622 1636
  ///
1623 1637
  inline LpBase::Constr operator<=(const LpBase::Expr &e,
1624 1638
                                   const LpBase::Value &f) {
1625 1639
    return LpBase::Constr(- LpBase::INF, e, f);
1626 1640
  }
1627 1641

	
1628 1642
  ///Create constraint
1629 1643

	
1630 1644
  ///\relates LpBase::Constr
1631 1645
  ///
1632 1646
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1633 1647
                                   const LpBase::Expr &f) {
1634 1648
    return LpBase::Constr(0, e - f, LpBase::INF);
1635 1649
  }
1636 1650

	
1637 1651

	
1638 1652
  ///Create constraint
1639 1653

	
1640 1654
  ///\relates LpBase::Constr
1641 1655
  ///
1642 1656
  inline LpBase::Constr operator>=(const LpBase::Value &e,
1643 1657
                                   const LpBase::Expr &f) {
1644 1658
    return LpBase::Constr(LpBase::NaN, f, e);
1645 1659
  }
1646 1660

	
1647 1661

	
1648 1662
  ///Create constraint
1649 1663

	
1650 1664
  ///\relates LpBase::Constr
1651 1665
  ///
1652 1666
  inline LpBase::Constr operator>=(const LpBase::Expr &e,
1653 1667
                                   const LpBase::Value &f) {
1654 1668
    return LpBase::Constr(f, e, LpBase::INF);
1655 1669
  }
1656 1670

	
1657 1671
  ///Create constraint
1658 1672

	
1659 1673
  ///\relates LpBase::Constr
1660 1674
  ///
1661 1675
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1662 1676
                                   const LpBase::Value &f) {
1663 1677
    return LpBase::Constr(f, e, f);
1664 1678
  }
1665 1679

	
1666 1680
  ///Create constraint
1667 1681

	
1668 1682
  ///\relates LpBase::Constr
1669 1683
  ///
1670 1684
  inline LpBase::Constr operator==(const LpBase::Expr &e,
1671 1685
                                   const LpBase::Expr &f) {
1672 1686
    return LpBase::Constr(0, f - e, 0);
1673 1687
  }
1674 1688

	
1675 1689
  ///Create constraint
1676 1690

	
1677 1691
  ///\relates LpBase::Constr
1678 1692
  ///
1679 1693
  inline LpBase::Constr operator<=(const LpBase::Value &n,
1680 1694
                                   const LpBase::Constr &c) {
1681 1695
    LpBase::Constr tmp(c);
1682 1696
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1683 1697
    tmp.lowerBound()=n;
1684 1698
    return tmp;
1685 1699
  }
1686 1700
  ///Create constraint
1687 1701

	
1688 1702
  ///\relates LpBase::Constr
1689 1703
  ///
1690 1704
  inline LpBase::Constr operator<=(const LpBase::Constr &c,
1691 1705
                                   const LpBase::Value &n)
1692 1706
  {
1693 1707
    LpBase::Constr tmp(c);
1694 1708
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1695 1709
    tmp.upperBound()=n;
1696 1710
    return tmp;
1697 1711
  }
1698 1712

	
1699 1713
  ///Create constraint
1700 1714

	
1701 1715
  ///\relates LpBase::Constr
1702 1716
  ///
1703 1717
  inline LpBase::Constr operator>=(const LpBase::Value &n,
1704 1718
                                   const LpBase::Constr &c) {
1705 1719
    LpBase::Constr tmp(c);
1706 1720
    LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
1707 1721
    tmp.upperBound()=n;
1708 1722
    return tmp;
1709 1723
  }
1710 1724
  ///Create constraint
1711 1725

	
1712 1726
  ///\relates LpBase::Constr
1713 1727
  ///
1714 1728
  inline LpBase::Constr operator>=(const LpBase::Constr &c,
1715 1729
                                   const LpBase::Value &n)
1716 1730
  {
1717 1731
    LpBase::Constr tmp(c);
1718 1732
    LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
1719 1733
    tmp.lowerBound()=n;
1720 1734
    return tmp;
1721 1735
  }
1722 1736

	
1723 1737
  ///Addition
1724 1738

	
1725 1739
  ///\relates LpBase::DualExpr
1726 1740
  ///
1727 1741
  inline LpBase::DualExpr operator+(const LpBase::DualExpr &a,
1728 1742
                                    const LpBase::DualExpr &b) {
1729 1743
    LpBase::DualExpr tmp(a);
1730 1744
    tmp+=b;
1731 1745
    return tmp;
1732 1746
  }
1733 1747
  ///Substraction
Show white space 1024 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
  int SkeletonSolverBase::_addRow(Value, ExprIterator, ExprIterator, Value)
36
  {
37
    return ++row_num;
38
  }
39

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

	
38 43
  void SkeletonSolverBase::_getColName(int, std::string &) const {}
39 44
  void SkeletonSolverBase::_setColName(int, const std::string &) {}
40 45
  int SkeletonSolverBase::_colByName(const std::string&) const { return -1; }
41 46

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

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

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

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

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

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

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

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

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

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

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

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

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

	
89 94
  LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; }
90 95

	
91 96
  LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; }
92 97
  LpSkeleton::Value LpSkeleton::_getDual(int) const { return 0; }
93 98
  LpSkeleton::Value LpSkeleton::_getPrimalValue() const { return 0; }
94 99

	
95 100
  LpSkeleton::Value LpSkeleton::_getPrimalRay(int) const { return 0; }
96 101
  LpSkeleton::Value LpSkeleton::_getDualRay(int) const { return 0; }
97 102

	
98 103
  LpSkeleton::ProblemType LpSkeleton::_getPrimalType() const
99 104
  { return UNDEFINED; }
100 105

	
101 106
  LpSkeleton::ProblemType LpSkeleton::_getDualType() const
102 107
  { return UNDEFINED; }
103 108

	
104 109
  LpSkeleton::VarStatus LpSkeleton::_getColStatus(int) const
105 110
  { return BASIC; }
106 111

	
107 112
  LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const
108 113
  { return BASIC; }
109 114

	
110 115
  LpSkeleton* LpSkeleton::newSolver() const
111 116
  { return static_cast<LpSkeleton*>(0); }
112 117

	
113 118
  LpSkeleton* LpSkeleton::cloneSolver() const
114 119
  { return static_cast<LpSkeleton*>(0); }
115 120

	
116 121
  const char* LpSkeleton::_solverName() const { return "LpSkeleton"; }
117 122

	
118 123
  MipSkeleton::SolveExitStatus MipSkeleton::_solve()
119 124
  { return SOLVED; }
120 125

	
121 126
  MipSkeleton::Value MipSkeleton::_getSol(int) const { return 0; }
122 127
  MipSkeleton::Value MipSkeleton::_getSolValue() const { return 0; }
123 128

	
124 129
  MipSkeleton::ProblemType MipSkeleton::_getType() const
125 130
  { return UNDEFINED; }
126 131

	
127 132
  MipSkeleton* MipSkeleton::newSolver() const
128 133
  { return static_cast<MipSkeleton*>(0); }
129 134

	
130 135
  MipSkeleton* MipSkeleton::cloneSolver() const
131 136
  { return static_cast<MipSkeleton*>(0); }
132 137

	
133 138
  const char* MipSkeleton::_solverName() const { return "MipSkeleton"; }
134 139

	
135 140
} //namespace lemon
136 141

	
Show white space 1024 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
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
49
    /// \e
48 50
    virtual void _eraseCol(int i);
49 51
    /// \e
50 52
    virtual void _eraseRow(int i);
51 53

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

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

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

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

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

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

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

	
92 94
    /// The upper bound of a variable (column) have to be given by an
93 95
    /// extended number of type Value, i.e. a finite number of type
94 96
    /// Value or \ref INF.
95 97
    virtual void _setColUpperBound(int i, Value value);
96 98
    /// \e
97 99

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

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

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

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

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

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

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

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

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

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

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

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

	
163 165
    ///\e
164 166
    virtual SolveExitStatus _solve();
165 167

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

	
171 173
    ///\e
172 174
    virtual Value _getPrimalValue() const;
173 175

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

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

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

	
189 191
    ///\e
190 192
    virtual const char* _solverName() const;
191 193

	
192 194
  };
193 195

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

	
208 210
  protected:
209 211
    ///\e
210 212
    virtual SolveExitStatus _solve();
211 213

	
212 214
    ///\e
213 215
    virtual Value _getSol(int i) const;
214 216

	
215 217
    ///\e
216 218
    virtual Value _getSolValue() const;
217 219

	
218 220
    ///\e
219 221
    virtual ProblemType _getType() const;
220 222

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

	
225 227
} //namespace lemon
226 228

	
227 229
#endif
Show white space 1024 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 23
#include <spxout.h>
24 24

	
25 25

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

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

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

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

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

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

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

	
52 52
    messageLevel(MESSAGE_NOTHING);
53 53
  }
54 54

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

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

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

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

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

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

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

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

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

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

	
94
  int SoplexLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
95
    soplex::DSVector v;
96
    for (ExprIterator it = b; it != e; ++it) {
97
      v.add(it->first, it->second);
98
    }
99
    soplex::LPRow r(l, v, u);
100
    soplex->addRow(r);
101

	
102
    _row_names.push_back(std::string());
103

	
104
    return soplex->nRows() - 1;
105
  }
106

	
94 107

	
95 108
  void SoplexLp::_eraseCol(int i) {
96 109
    soplex->removeCol(i);
97 110
    _col_names_ref.erase(_col_names[i]);
98 111
    _col_names[i] = _col_names.back();
99 112
    _col_names_ref[_col_names.back()] = i;
100 113
    _col_names.pop_back();
101 114
  }
102 115

	
103 116
  void SoplexLp::_eraseRow(int i) {
104 117
    soplex->removeRow(i);
105 118
    _row_names_ref.erase(_row_names[i]);
106 119
    _row_names[i] = _row_names.back();
107 120
    _row_names_ref[_row_names.back()] = i;
108 121
    _row_names.pop_back();
109 122
  }
110 123

	
111 124
  void SoplexLp::_eraseColId(int i) {
112 125
    cols.eraseIndex(i);
113 126
    cols.relocateIndex(i, cols.maxIndex());
114 127
  }
115 128
  void SoplexLp::_eraseRowId(int i) {
116 129
    rows.eraseIndex(i);
117 130
    rows.relocateIndex(i, rows.maxIndex());
118 131
  }
119 132

	
120 133
  void SoplexLp::_getColName(int c, std::string &name) const {
121 134
    name = _col_names[c];
122 135
  }
123 136

	
124 137
  void SoplexLp::_setColName(int c, const std::string &name) {
125 138
    _col_names_ref.erase(_col_names[c]);
126 139
    _col_names[c] = name;
127 140
    if (!name.empty()) {
128 141
      _col_names_ref.insert(std::make_pair(name, c));
129 142
    }
130 143
  }
131 144

	
132 145
  int SoplexLp::_colByName(const std::string& name) const {
133 146
    std::map<std::string, int>::const_iterator it =
134 147
      _col_names_ref.find(name);
135 148
    if (it != _col_names_ref.end()) {
136 149
      return it->second;
137 150
    } else {
138 151
      return -1;
139 152
    }
140 153
  }
141 154

	
142 155
  void SoplexLp::_getRowName(int r, std::string &name) const {
143 156
    name = _row_names[r];
144 157
  }
145 158

	
146 159
  void SoplexLp::_setRowName(int r, const std::string &name) {
147 160
    _row_names_ref.erase(_row_names[r]);
148 161
    _row_names[r] = name;
149 162
    if (!name.empty()) {
150 163
      _row_names_ref.insert(std::make_pair(name, r));
151 164
    }
152 165
  }
153 166

	
154 167
  int SoplexLp::_rowByName(const std::string& name) const {
155 168
    std::map<std::string, int>::const_iterator it =
156 169
      _row_names_ref.find(name);
157 170
    if (it != _row_names_ref.end()) {
158 171
      return it->second;
159 172
    } else {
160 173
      return -1;
161 174
    }
162 175
  }
163 176

	
164 177

	
165 178
  void SoplexLp::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
166 179
    for (int j = 0; j < soplex->nCols(); ++j) {
167 180
      soplex->changeElement(i, j, 0.0);
168 181
    }
169 182
    for(ExprIterator it = b; it != e; ++it) {
170 183
      soplex->changeElement(i, it->first, it->second);
171 184
    }
172 185
  }
173 186

	
174 187
  void SoplexLp::_getRowCoeffs(int i, InsertIterator b) const {
175 188
    const soplex::SVector& vec = soplex->rowVector(i);
176 189
    for (int k = 0; k < vec.size(); ++k) {
177 190
      *b = std::make_pair(vec.index(k), vec.value(k));
178 191
      ++b;
179 192
    }
180 193
  }
181 194

	
182 195
  void SoplexLp::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
183 196
    for (int i = 0; i < soplex->nRows(); ++i) {
184 197
      soplex->changeElement(i, j, 0.0);
185 198
    }
186 199
    for(ExprIterator it = b; it != e; ++it) {
187 200
      soplex->changeElement(it->first, j, it->second);
188 201
    }
189 202
  }
190 203

	
191 204
  void SoplexLp::_getColCoeffs(int i, InsertIterator b) const {
192 205
    const soplex::SVector& vec = soplex->colVector(i);
193 206
    for (int k = 0; k < vec.size(); ++k) {
194 207
      *b = std::make_pair(vec.index(k), vec.value(k));
195 208
      ++b;
196 209
    }
197 210
  }
198 211

	
199 212
  void SoplexLp::_setCoeff(int i, int j, Value value) {
200 213
    soplex->changeElement(i, j, value);
201 214
  }
202 215

	
203 216
  SoplexLp::Value SoplexLp::_getCoeff(int i, int j) const {
204 217
    return soplex->rowVector(i)[j];
205 218
  }
206 219

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

	
212 225
  SoplexLp::Value SoplexLp::_getColLowerBound(int i) const {
213 226
    double value = soplex->lower(i);
214 227
    return value != -soplex::infinity ? value : -INF;
215 228
  }
216 229

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

	
222 235
  SoplexLp::Value SoplexLp::_getColUpperBound(int i) const {
223 236
    double value = soplex->upper(i);
224 237
    return value != soplex::infinity ? value : INF;
225 238
  }
226 239

	
227 240
  void SoplexLp::_setRowLowerBound(int i, Value lb) {
228 241
    LEMON_ASSERT(lb != INF, "Invalid bound");
229 242
    soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
230 243
  }
231 244

	
232 245
  SoplexLp::Value SoplexLp::_getRowLowerBound(int i) const {
233 246
    double res = soplex->lhs(i);
234 247
    return res == -soplex::infinity ? -INF : res;
235 248
  }
236 249

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

	
242 255
  SoplexLp::Value SoplexLp::_getRowUpperBound(int i) const {
243 256
    double res = soplex->rhs(i);
244 257
    return res == soplex::infinity ? INF : res;
245 258
  }
246 259

	
247 260
  void SoplexLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
248 261
    for (int j = 0; j < soplex->nCols(); ++j) {
249 262
      soplex->changeObj(j, 0.0);
250 263
    }
251 264
    for (ExprIterator it = b; it != e; ++it) {
252 265
      soplex->changeObj(it->first, it->second);
253 266
    }
254 267
  }
255 268

	
256 269
  void SoplexLp::_getObjCoeffs(InsertIterator b) const {
257 270
    for (int j = 0; j < soplex->nCols(); ++j) {
258 271
      Value coef = soplex->obj(j);
259 272
      if (coef != 0.0) {
260 273
        *b = std::make_pair(j, coef);
261 274
        ++b;
262 275
      }
263 276
    }
264 277
  }
265 278

	
266 279
  void SoplexLp::_setObjCoeff(int i, Value obj_coef) {
267 280
    soplex->changeObj(i, obj_coef);
268 281
  }
269 282

	
270 283
  SoplexLp::Value SoplexLp::_getObjCoeff(int i) const {
271 284
    return soplex->obj(i);
272 285
  }
273 286

	
274 287
  SoplexLp::SolveExitStatus SoplexLp::_solve() {
275 288

	
276 289
    _clear_temporals();
277 290
    
278 291
    _applyMessageLevel();
279 292

	
280 293
    soplex::SPxSolver::Status status = soplex->solve();
281 294

	
282 295
    switch (status) {
283 296
    case soplex::SPxSolver::OPTIMAL:
284 297
    case soplex::SPxSolver::INFEASIBLE:
285 298
    case soplex::SPxSolver::UNBOUNDED:
286 299
      return SOLVED;
287 300
    default:
288 301
      return UNSOLVED;
289 302
    }
290 303
  }
291 304

	
292 305
  SoplexLp::Value SoplexLp::_getPrimal(int i) const {
293 306
    if (_primal_values.empty()) {
294 307
      _primal_values.resize(soplex->nCols());
295 308
      soplex::Vector pv(_primal_values.size(), &_primal_values.front());
296 309
      soplex->getPrimal(pv);
297 310
    }
298 311
    return _primal_values[i];
299 312
  }
300 313

	
301 314
  SoplexLp::Value SoplexLp::_getDual(int i) const {
302 315
    if (_dual_values.empty()) {
303 316
      _dual_values.resize(soplex->nRows());
304 317
      soplex::Vector dv(_dual_values.size(), &_dual_values.front());
305 318
      soplex->getDual(dv);
306 319
    }
307 320
    return _dual_values[i];
308 321
  }
309 322

	
310 323
  SoplexLp::Value SoplexLp::_getPrimalValue() const {
311 324
    return soplex->objValue();
312 325
  }
313 326

	
314 327
  SoplexLp::VarStatus SoplexLp::_getColStatus(int i) const {
315 328
    switch (soplex->getBasisColStatus(i)) {
316 329
    case soplex::SPxSolver::BASIC:
317 330
      return BASIC;
318 331
    case soplex::SPxSolver::ON_UPPER:
319 332
      return UPPER;
320 333
    case soplex::SPxSolver::ON_LOWER:
321 334
      return LOWER;
322 335
    case soplex::SPxSolver::FIXED:
323 336
      return FIXED;
324 337
    case soplex::SPxSolver::ZERO:
325 338
      return FREE;
326 339
    default:
327 340
      LEMON_ASSERT(false, "Wrong column status");
328 341
      return VarStatus();
329 342
    }
330 343
  }
331 344

	
332 345
  SoplexLp::VarStatus SoplexLp::_getRowStatus(int i) const {
333 346
    switch (soplex->getBasisRowStatus(i)) {
334 347
    case soplex::SPxSolver::BASIC:
335 348
      return BASIC;
336 349
    case soplex::SPxSolver::ON_UPPER:
337 350
      return UPPER;
338 351
    case soplex::SPxSolver::ON_LOWER:
339 352
      return LOWER;
340 353
    case soplex::SPxSolver::FIXED:
341 354
      return FIXED;
342 355
    case soplex::SPxSolver::ZERO:
343 356
      return FREE;
344 357
    default:
345 358
      LEMON_ASSERT(false, "Wrong row status");
346 359
      return VarStatus();
347 360
    }
348 361
  }
349 362

	
350 363
  SoplexLp::Value SoplexLp::_getPrimalRay(int i) const {
351 364
    if (_primal_ray.empty()) {
352 365
      _primal_ray.resize(soplex->nCols());
353 366
      soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
354 367
      soplex->getDualfarkas(pv);
355 368
    }
356 369
    return _primal_ray[i];
357 370
  }
358 371

	
359 372
  SoplexLp::Value SoplexLp::_getDualRay(int i) const {
360 373
    if (_dual_ray.empty()) {
361 374
      _dual_ray.resize(soplex->nRows());
362 375
      soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
363 376
      soplex->getDualfarkas(dv);
364 377
    }
365 378
    return _dual_ray[i];
366 379
  }
367 380

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

	
381 394
  SoplexLp::ProblemType SoplexLp::_getDualType() const {
382 395
    switch (soplex->status()) {
383 396
    case soplex::SPxSolver::OPTIMAL:
384 397
      return OPTIMAL;
385 398
    case soplex::SPxSolver::UNBOUNDED:
386 399
      return UNBOUNDED;
387 400
    case soplex::SPxSolver::INFEASIBLE:
388 401
      return INFEASIBLE;
389 402
    default:
390 403
      return UNDEFINED;
391 404
    }
392 405
  }
393 406

	
394 407
  void SoplexLp::_setSense(Sense sense) {
395 408
    switch (sense) {
396 409
    case MIN:
397 410
      soplex->changeSense(soplex::SPxSolver::MINIMIZE);
398 411
      break;
399 412
    case MAX:
400 413
      soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
401 414
    }
402 415
  }
403 416

	
404 417
  SoplexLp::Sense SoplexLp::_getSense() const {
405 418
    switch (soplex->spxSense()) {
406 419
    case soplex::SPxSolver::MAXIMIZE:
407 420
      return MAX;
408 421
    case soplex::SPxSolver::MINIMIZE:
409 422
      return MIN;
410 423
    default:
411 424
      LEMON_ASSERT(false, "Wrong sense.");
412 425
      return SoplexLp::Sense();
413 426
    }
414 427
  }
415 428

	
416 429
  void SoplexLp::_clear() {
417 430
    soplex->clear();
418 431
    _col_names.clear();
419 432
    _col_names_ref.clear();
420 433
    _row_names.clear();
421 434
    _row_names_ref.clear();
422 435
    cols.clear();
423 436
    rows.clear();
424 437
    _clear_temporals();
425 438
  }
426 439

	
427 440
  void SoplexLp::_messageLevel(MessageLevel level) {
428 441
    switch (level) {
429 442
    case MESSAGE_NOTHING:
430 443
      _message_level = -1;
431 444
      break;
432 445
    case MESSAGE_ERROR:
433 446
      _message_level = soplex::SPxOut::ERROR;
434 447
      break;
435 448
    case MESSAGE_WARNING:
436 449
      _message_level = soplex::SPxOut::WARNING;
437 450
      break;
438 451
    case MESSAGE_NORMAL:
439 452
      _message_level = soplex::SPxOut::INFO2;
440 453
      break;
441 454
    case MESSAGE_VERBOSE:
442 455
      _message_level = soplex::SPxOut::DEBUG;
443 456
      break;
444 457
    }
445 458
  }
446 459

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

	
451 464
} //namespace lemon
452 465

	
Show white space 1024 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
    virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
87 88

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

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

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

	
98 99
    virtual void _getRowName(int row, std::string& name) const;
99 100
    virtual void _setRowName(int row, const std::string& name);
100 101
    virtual int _rowByName(const std::string& name) const;
101 102

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

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

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

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

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

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

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

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

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

	
134 135
    virtual Value _getPrimalValue() const;
135 136

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

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

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

	
145 146
    virtual void _clear();
146 147

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

	
150 151
    int _message_level;
151 152

	
152 153
  };
153 154

	
154 155
} //END OF NAMESPACE LEMON
155 156

	
156 157
#endif //LEMON_SOPLEX_H
157 158

	
0 comments (0 inline)