gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Fix newSolver()/cloneSolver() API in LP tools + doc improvements (#230) - More logical structure for newSolver()/cloneSolver() - Fix compilation problem with gcc-3.3 - Doc improvements
0 13 0
default
13 files changed with 118 insertions and 78 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -11,102 +11,102 @@
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_NO_OUTPUT);
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_NO_OUTPUT);
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
  ClpLp* ClpLp::_newSolver() const {
59
  ClpLp* ClpLp::newSolver() const {
60 60
    ClpLp* newlp = new ClpLp;
61 61
    return newlp;
62 62
  }
63 63

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

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

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

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

	
81 81

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

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

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

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

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

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

	
111 111
  int ClpLp::_colByName(const std::string& name) const {
112 112
    std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
Ignore white space 6 line context
... ...
@@ -11,109 +11,111 @@
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
    /// \e
60
    virtual ClpLp* newSolver() const;
61
    /// \e
62
    virtual ClpLp* cloneSolver() const;
63

	
59 64
  protected:
60 65

	
61 66
    mutable double* _primal_ray;
62 67
    mutable double* _dual_ray;
63 68

	
64 69
    void _init_temporals();
65 70
    void _clear_temporals();
66 71

	
67 72
  protected:
68 73

	
69
    virtual ClpLp* _newSolver() const;
70
    virtual ClpLp* _cloneSolver() const;
71

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
119 121
    virtual SolveExitStatus _solve();
Ignore white space 6 line context
... ...
@@ -406,98 +406,98 @@
406 406
    CPXgetobj(cplexEnv(), _prob, &x, i, i);
407 407
    return x;
408 408
  }
409 409

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

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

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

	
441 441
  // CplexLp members
442 442

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

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

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

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

	
454
  CplexLp* CplexLp::_newSolver() const { return new CplexLp; }
455
  CplexLp* CplexLp::_cloneSolver() const {return new CplexLp(*this); }
454
  CplexLp* CplexLp::newSolver() const { return new CplexLp; }
455
  CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
456 456

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

	
459 459
  void CplexLp::_clear_temporals() {
460 460
    _col_status.clear();
461 461
    _row_status.clear();
462 462
    _primal_ray.clear();
463 463
    _dual_ray.clear();
464 464
  }
465 465

	
466 466
  // The routine returns zero unless an error occurred during the
467 467
  // optimization. Examples of errors include exhausting available
468 468
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
469 469
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
470 470
  // user-specified CPLEX limit, or proving the model infeasible or
471 471
  // unbounded, are not considered errors. Note that a zero return
472 472
  // value does not necessarily mean that a solution exists. Use query
473 473
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
474 474
  // further information about the status of the optimization.
475 475
  CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
476 476
#if CPX_VERSION >= 800
477 477
    if (status == 0) {
478 478
      switch (CPXgetstat(cplexEnv(), _prob)) {
479 479
      case CPX_STAT_OPTIMAL:
480 480
      case CPX_STAT_INFEASIBLE:
481 481
      case CPX_STAT_UNBOUNDED:
482 482
        return SOLVED;
483 483
      default:
484 484
        return UNSOLVED;
485 485
      }
486 486
    } else {
487 487
      return UNSOLVED;
488 488
    }
489 489
#else
490 490
    if (status == 0) {
491 491
      //We want to exclude some cases
492 492
      switch (CPXgetstat(cplexEnv(), _prob)) {
493 493
      case CPX_OBJ_LIM:
494 494
      case CPX_IT_LIM_FEAS:
495 495
      case CPX_IT_LIM_INFEAS:
496 496
      case CPX_TIME_LIM_FEAS:
497 497
      case CPX_TIME_LIM_INFEAS:
498 498
        return UNSOLVED;
499 499
      default:
500 500
        return SOLVED;
501 501
      }
502 502
    } else {
503 503
      return UNSOLVED;
... ...
@@ -778,98 +778,98 @@
778 778
      return INFEASIBLE;
779 779
    default:
780 780
      return UNDEFINED;
781 781
    }
782 782
#else
783 783
    statusSwitch(cplexEnv(),stat);
784 784
    switch (stat) {
785 785
    case 0:
786 786
      return UNDEFINED; //Undefined
787 787
    case CPX_OPTIMAL://Optimal
788 788
      return OPTIMAL;
789 789
    case CPX_UNBOUNDED:
790 790
      return INFEASIBLE;
791 791
    default:
792 792
      return UNDEFINED; //Everything else comes here
793 793
      //FIXME error
794 794
    }
795 795
#endif
796 796
  }
797 797

	
798 798
  // CplexMip members
799 799

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

	
803 803
#if CPX_VERSION < 800
804 804
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
805 805
#else
806 806
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
807 807
#endif
808 808
  }
809 809

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

	
813 813
#if CPX_VERSION < 800
814 814
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
815 815
#else
816 816
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
817 817
#endif
818 818

	
819 819
  }
820 820

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

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

	
826
  CplexMip* CplexMip::_newSolver() const { return new CplexMip; }
827
  CplexMip* CplexMip::_cloneSolver() const {return new CplexMip(*this); }
826
  CplexMip* CplexMip::newSolver() const { return new CplexMip; }
827
  CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
828 828

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

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

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

	
836 836
    switch (col_type){
837 837
    case INTEGER: {
838 838
      const char t = 'I';
839 839
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
840 840
    } break;
841 841
    case REAL: {
842 842
      const char t = 'C';
843 843
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
844 844
    } break;
845 845
    default:
846 846
      break;
847 847
    }
848 848
  }
849 849

	
850 850
  CplexMip::ColTypes CplexMip::_getColType(int i) const {
851 851
    char t;
852 852
    CPXgetctype (cplexEnv(), _prob, &t, i, i);
853 853
    switch (t) {
854 854
    case 'I':
855 855
      return INTEGER;
856 856
    case 'C':
857 857
      return REAL;
858 858
    default:
859 859
      LEMON_ASSERT(false, "Invalid column type");
860 860
      return ColTypes();
861 861
    }
862 862

	
863 863
  }
864 864

	
865 865
  CplexMip::SolveExitStatus CplexMip::_solve() {
866 866
    int status;
867 867
    status = CPXmipopt (cplexEnv(), _prob);
868 868
    if (status==0)
869 869
      return SOLVED;
870 870
    else
871 871
      return UNSOLVED;
872 872

	
873 873
  }
874 874

	
875 875

	
Ignore white space 6 line context
... ...
@@ -115,142 +115,144 @@
115 115
    virtual void _getColCoeffs(int i, InsertIterator b) const;
116 116

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

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

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

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

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

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

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

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

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

	
145 145
    virtual void _clear();
146 146

	
147 147
  public:
148 148

	
149 149
    /// Returns the used \c CplexEnv instance
150 150
    const CplexEnv& env() const { return _env; }
151 151
    ///
152 152
    const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
153 153

	
154 154
    cpxlp* cplexLp() { return _prob; }
155 155
    const cpxlp* cplexLp() const { return _prob; }
156 156

	
157 157
  };
158 158

	
159 159
  /// \brief Interface for the CPLEX LP solver
160 160
  ///
161 161
  /// This class implements an interface for the CPLEX LP solver.
162 162
  ///\ingroup lp_group
163
  class CplexLp : public CplexBase, public LpSolver {
163
  class CplexLp : public LpSolver, public CplexBase {
164 164
  public:
165 165
    /// \e
166 166
    CplexLp();
167 167
    /// \e
168 168
    CplexLp(const CplexEnv&);
169 169
    /// \e
170 170
    CplexLp(const CplexLp&);
171 171
    /// \e
172 172
    virtual ~CplexLp();
173 173

	
174
    /// \e
175
    virtual CplexLp* cloneSolver() const;
176
    /// \e
177
    virtual CplexLp* newSolver() const;
178

	
174 179
  private:
175 180

	
176 181
    // these values cannot retrieved element by element
177 182
    mutable std::vector<int> _col_status;
178 183
    mutable std::vector<int> _row_status;
179 184

	
180 185
    mutable std::vector<Value> _primal_ray;
181 186
    mutable std::vector<Value> _dual_ray;
182 187

	
183 188
    void _clear_temporals();
184 189

	
185 190
    SolveExitStatus convertStatus(int status);
186 191

	
187 192
  protected:
188 193

	
189
    virtual CplexLp* _cloneSolver() const;
190
    virtual CplexLp* _newSolver() const;
191

	
192 194
    virtual const char* _solverName() const;
193 195

	
194 196
    virtual SolveExitStatus _solve();
195 197
    virtual Value _getPrimal(int i) const;
196 198
    virtual Value _getDual(int i) const;
197 199
    virtual Value _getPrimalValue() const;
198 200

	
199 201
    virtual VarStatus _getColStatus(int i) const;
200 202
    virtual VarStatus _getRowStatus(int i) const;
201 203

	
202 204
    virtual Value _getPrimalRay(int i) const;
203 205
    virtual Value _getDualRay(int i) const;
204 206

	
205 207
    virtual ProblemType _getPrimalType() const;
206 208
    virtual ProblemType _getDualType() const;
207 209

	
208 210
  public:
209 211

	
210 212
    /// Solve with primal simplex method
211 213
    SolveExitStatus solvePrimal();
212 214

	
213 215
    /// Solve with dual simplex method
214 216
    SolveExitStatus solveDual();
215 217

	
216 218
    /// Solve with barrier method
217 219
    SolveExitStatus solveBarrier();
218 220

	
219 221
  };
220 222

	
221 223
  /// \brief Interface for the CPLEX MIP solver
222 224
  ///
223 225
  /// This class implements an interface for the CPLEX MIP solver.
224 226
  ///\ingroup lp_group
225
  class CplexMip : public CplexBase, public MipSolver {
227
  class CplexMip : public MipSolver, public CplexBase {
226 228
  public:
227 229
    /// \e
228 230
    CplexMip();
229 231
    /// \e
230 232
    CplexMip(const CplexEnv&);
231 233
    /// \e
232 234
    CplexMip(const CplexMip&);
233 235
    /// \e
234 236
    virtual ~CplexMip();
235 237

	
236 238
  protected:
237 239

	
238 240
    virtual CplexMip* _cloneSolver() const;
239 241
    virtual CplexMip* _newSolver() const;
240 242

	
241 243
    virtual const char* _solverName() const;
242 244

	
243 245
    virtual ColTypes _getColType(int col) const;
244 246
    virtual void _setColType(int col, ColTypes col_type);
245 247

	
246 248
    virtual SolveExitStatus _solve();
247 249
    virtual ProblemType _getType() const;
248 250
    virtual Value _getSol(int i) const;
249 251
    virtual Value _getSolValue() const;
250 252

	
251 253
  };
252 254

	
253 255
} //END OF NAMESPACE LEMON
254 256

	
255 257
#endif //LEMON_CPLEX_H
256 258

	
Ignore white space 6 line context
... ...
@@ -489,98 +489,98 @@
489 489
  }
490 490

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

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

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

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

	
525 525
  // GlpkLp members
526 526

	
527 527
  GlpkLp::GlpkLp()
528 528
    : LpBase(), GlpkBase(), LpSolver() {
529 529
    messageLevel(MESSAGE_NO_OUTPUT);
530 530
  }
531 531

	
532 532
  GlpkLp::GlpkLp(const GlpkLp& other)
533 533
    : LpBase(other), GlpkBase(other), LpSolver(other) {
534 534
    messageLevel(MESSAGE_NO_OUTPUT);
535 535
  }
536 536

	
537
  GlpkLp* GlpkLp::_newSolver() const { return new GlpkLp; }
538
  GlpkLp* GlpkLp::_cloneSolver() const { return new GlpkLp(*this); }
537
  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
538
  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
539 539

	
540 540
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
541 541

	
542 542
  void GlpkLp::_clear_temporals() {
543 543
    _primal_ray.clear();
544 544
    _dual_ray.clear();
545 545
  }
546 546

	
547 547
  GlpkLp::SolveExitStatus GlpkLp::_solve() {
548 548
    return solvePrimal();
549 549
  }
550 550

	
551 551
  GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
552 552
    _clear_temporals();
553 553

	
554 554
    glp_smcp smcp;
555 555
    glp_init_smcp(&smcp);
556 556

	
557 557
    switch (_message_level) {
558 558
    case MESSAGE_NO_OUTPUT:
559 559
      smcp.msg_lev = GLP_MSG_OFF;
560 560
      break;
561 561
    case MESSAGE_ERROR_MESSAGE:
562 562
      smcp.msg_lev = GLP_MSG_ERR;
563 563
      break;
564 564
    case MESSAGE_NORMAL_OUTPUT:
565 565
      smcp.msg_lev = GLP_MSG_ON;
566 566
      break;
567 567
    case MESSAGE_FULL_OUTPUT:
568 568
      smcp.msg_lev = GLP_MSG_ALL;
569 569
      break;
570 570
    }
571 571

	
572 572
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
573 573
    return SOLVED;
574 574
  }
575 575

	
576 576
  GlpkLp::SolveExitStatus GlpkLp::solveDual() {
577 577
    _clear_temporals();
578 578

	
579 579
    glp_smcp smcp;
580 580
    glp_init_smcp(&smcp);
581 581

	
582 582
    switch (_message_level) {
583 583
    case MESSAGE_NO_OUTPUT:
584 584
      smcp.msg_lev = GLP_MSG_OFF;
585 585
      break;
586 586
    case MESSAGE_ERROR_MESSAGE:
... ...
@@ -895,58 +895,58 @@
895 895
      iocp.msg_lev = GLP_MSG_ALL;
896 896
      break;
897 897
    }
898 898

	
899 899
    if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
900 900
    return SOLVED;
901 901
  }
902 902

	
903 903

	
904 904
  GlpkMip::ProblemType GlpkMip::_getType() const {
905 905
    switch (glp_get_status(lp)) {
906 906
    case GLP_OPT:
907 907
      switch (glp_mip_status(lp)) {
908 908
      case GLP_UNDEF:
909 909
        return UNDEFINED;
910 910
      case GLP_NOFEAS:
911 911
        return INFEASIBLE;
912 912
      case GLP_FEAS:
913 913
        return FEASIBLE;
914 914
      case GLP_OPT:
915 915
        return OPTIMAL;
916 916
      default:
917 917
        LEMON_ASSERT(false, "Wrong problem type.");
918 918
        return GlpkMip::ProblemType();
919 919
      }
920 920
    case GLP_NOFEAS:
921 921
      return INFEASIBLE;
922 922
    case GLP_INFEAS:
923 923
    case GLP_FEAS:
924 924
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
925 925
        return UNBOUNDED;
926 926
      } else {
927 927
        return UNDEFINED;
928 928
      }
929 929
    default:
930 930
      LEMON_ASSERT(false, "Wrong problem type.");
931 931
      return GlpkMip::ProblemType();
932 932
    }
933 933
  }
934 934

	
935 935
  GlpkMip::Value GlpkMip::_getSol(int i) const {
936 936
    return glp_mip_col_val(lp, i);
937 937
  }
938 938

	
939 939
  GlpkMip::Value GlpkMip::_getSolValue() const {
940 940
    return glp_mip_obj_val(lp);
941 941
  }
942 942

	
943
  GlpkMip* GlpkMip::_newSolver() const { return new GlpkMip; }
944
  GlpkMip* GlpkMip::_cloneSolver() const {return new GlpkMip(*this); }
943
  GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; }
944
  GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); }
945 945

	
946 946
  const char* GlpkMip::_solverName() const { return "GlpkMip"; }
947 947

	
948 948
  void GlpkMip::messageLevel(MessageLevel m) {
949 949
    _message_level = m;
950 950
  }
951 951

	
952 952
} //END OF NAMESPACE LEMON
Ignore white space 6 line context
... ...
@@ -74,186 +74,188 @@
74 74
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
75 75
    virtual void _getColCoeffs(int i, InsertIterator b) const;
76 76

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

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

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

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

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

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

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

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

	
101 101
    virtual void _clear();
102 102

	
103 103
  public:
104 104

	
105 105
    ///Pointer to the underlying GLPK data structure.
106 106
    LPX *lpx() {return lp;}
107 107
    ///Const pointer to the underlying GLPK data structure.
108 108
    const LPX *lpx() const {return lp;}
109 109

	
110 110
    ///Returns the constraint identifier understood by GLPK.
111 111
    int lpxRow(Row r) const { return rows(id(r)); }
112 112

	
113 113
    ///Returns the variable identifier understood by GLPK.
114 114
    int lpxCol(Col c) const { return cols(id(c)); }
115 115

	
116 116
  };
117 117

	
118 118
  /// \brief Interface for the GLPK LP solver
119 119
  ///
120 120
  /// This class implements an interface for the GLPK LP solver.
121 121
  ///\ingroup lp_group
122
  class GlpkLp : public GlpkBase, public LpSolver {
122
  class GlpkLp : public LpSolver, public GlpkBase {
123 123
  public:
124 124

	
125 125
    ///\e
126 126
    GlpkLp();
127 127
    ///\e
128 128
    GlpkLp(const GlpkLp&);
129 129

	
130
    ///\e
131
    virtual GlpkLp* cloneSolver() const;
132
    ///\e
133
    virtual GlpkLp* newSolver() const;
134

	
130 135
  private:
131 136

	
132 137
    mutable std::vector<double> _primal_ray;
133 138
    mutable std::vector<double> _dual_ray;
134 139

	
135 140
    void _clear_temporals();
136 141

	
137 142
  protected:
138 143

	
139
    virtual GlpkLp* _cloneSolver() const;
140
    virtual GlpkLp* _newSolver() const;
141

	
142 144
    virtual const char* _solverName() const;
143 145

	
144 146
    virtual SolveExitStatus _solve();
145 147
    virtual Value _getPrimal(int i) const;
146 148
    virtual Value _getDual(int i) const;
147 149

	
148 150
    virtual Value _getPrimalValue() const;
149 151

	
150 152
    virtual VarStatus _getColStatus(int i) const;
151 153
    virtual VarStatus _getRowStatus(int i) const;
152 154

	
153 155
    virtual Value _getPrimalRay(int i) const;
154 156
    virtual Value _getDualRay(int i) const;
155 157

	
156 158
    ///\todo It should be clarified
157 159
    ///
158 160
    virtual ProblemType _getPrimalType() const;
159 161
    virtual ProblemType _getDualType() const;
160 162

	
161 163
  public:
162 164

	
163 165
    ///Solve with primal simplex
164 166
    SolveExitStatus solvePrimal();
165 167

	
166 168
    ///Solve with dual simplex
167 169
    SolveExitStatus solveDual();
168 170

	
169 171
    ///Turns on or off the presolver
170 172

	
171 173
    ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
172 174
    ///
173 175
    ///The presolver is off by default.
174 176
    void presolver(bool b);
175 177

	
176 178
    ///Enum for \c messageLevel() parameter
177 179
    enum MessageLevel {
178 180
      /// no output (default value)
179 181
      MESSAGE_NO_OUTPUT = 0,
180 182
      /// error messages only
181 183
      MESSAGE_ERROR_MESSAGE = 1,
182 184
      /// normal output
183 185
      MESSAGE_NORMAL_OUTPUT = 2,
184 186
      /// full output (includes informational messages)
185 187
      MESSAGE_FULL_OUTPUT = 3
186 188
    };
187 189

	
188 190
  private:
189 191

	
190 192
    MessageLevel _message_level;
191 193

	
192 194
  public:
193 195

	
194 196
    ///Set the verbosity of the messages
195 197

	
196 198
    ///Set the verbosity of the messages
197 199
    ///
198 200
    ///\param m is the level of the messages output by the solver routines.
199 201
    void messageLevel(MessageLevel m);
200 202
  };
201 203

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

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

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

	
214 219
  protected:
215 220

	
216
    virtual GlpkMip* _cloneSolver() const;
217
    virtual GlpkMip* _newSolver() const;
218

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

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

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

	
229 231
    ///Enum for \c messageLevel() parameter
230 232
    enum MessageLevel {
231 233
      /// no output (default value)
232 234
      MESSAGE_NO_OUTPUT = 0,
233 235
      /// error messages only
234 236
      MESSAGE_ERROR_MESSAGE = 1,
235 237
      /// normal output
236 238
      MESSAGE_NORMAL_OUTPUT = 2,
237 239
      /// full output (includes informational messages)
238 240
      MESSAGE_FULL_OUTPUT = 3
239 241
    };
240 242

	
241 243
  private:
242 244

	
243 245
    MessageLevel _message_level;
244 246

	
245 247
  public:
246 248

	
247 249
    ///Set the verbosity of the messages
248 250

	
249 251
    ///Set the verbosity of the messages
250 252
    ///
251 253
    ///\param m is the level of the messages output by the solver routines.
252 254
    void messageLevel(MessageLevel m);
253 255
  };
254 256

	
255 257

	
256 258
} //END OF NAMESPACE LEMON
257 259

	
258 260
#endif //LEMON_GLPK_H
259 261

	
Ignore white space 6 line context
... ...
@@ -873,170 +873,163 @@
873 873
      typedef std::bidirectional_iterator_tag iterator_category;
874 874
      typedef std::ptrdiff_t difference_type;
875 875
      typedef const std::pair<int, Value> value_type;
876 876
      typedef value_type reference;
877 877

	
878 878
      class pointer {
879 879
      public:
880 880
        pointer(value_type& _value) : value(_value) {}
881 881
        value_type* operator->() { return &value; }
882 882
      private:
883 883
        value_type value;
884 884
      };
885 885

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

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

	
894 894
      pointer operator->() {
895 895
        return pointer(operator*());
896 896
      }
897 897

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

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

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

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

	
916 916
    };
917 917

	
918 918
  protected:
919 919

	
920 920
    //Abstract virtual functions
921
    virtual LpBase* _newSolver() const = 0;
922
    virtual LpBase* _cloneSolver() const = 0;
923 921

	
924 922
    virtual int _addColId(int col) { return cols.addIndex(col); }
925 923
    virtual int _addRowId(int row) { return rows.addIndex(row); }
926 924

	
927 925
    virtual void _eraseColId(int col) { cols.eraseIndex(col); }
928 926
    virtual void _eraseRowId(int row) { rows.eraseIndex(row); }
929 927

	
930 928
    virtual int _addCol() = 0;
931 929
    virtual int _addRow() = 0;
932 930

	
933 931
    virtual void _eraseCol(int col) = 0;
934 932
    virtual void _eraseRow(int row) = 0;
935 933

	
936 934
    virtual void _getColName(int col, std::string& name) const = 0;
937 935
    virtual void _setColName(int col, const std::string& name) = 0;
938 936
    virtual int _colByName(const std::string& name) const = 0;
939 937

	
940 938
    virtual void _getRowName(int row, std::string& name) const = 0;
941 939
    virtual void _setRowName(int row, const std::string& name) = 0;
942 940
    virtual int _rowByName(const std::string& name) const = 0;
943 941

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

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

	
950 948
    virtual void _setCoeff(int row, int col, Value value) = 0;
951 949
    virtual Value _getCoeff(int row, int col) const = 0;
952 950

	
953 951
    virtual void _setColLowerBound(int i, Value value) = 0;
954 952
    virtual Value _getColLowerBound(int i) const = 0;
955 953

	
956 954
    virtual void _setColUpperBound(int i, Value value) = 0;
957 955
    virtual Value _getColUpperBound(int i) const = 0;
958 956

	
959 957
    virtual void _setRowLowerBound(int i, Value value) = 0;
960 958
    virtual Value _getRowLowerBound(int i) const = 0;
961 959

	
962 960
    virtual void _setRowUpperBound(int i, Value value) = 0;
963 961
    virtual Value _getRowUpperBound(int i) const = 0;
964 962

	
965 963
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e) = 0;
966 964
    virtual void _getObjCoeffs(InsertIterator b) const = 0;
967 965

	
968 966
    virtual void _setObjCoeff(int i, Value obj_coef) = 0;
969 967
    virtual Value _getObjCoeff(int i) const = 0;
970 968

	
971 969
    virtual void _setSense(Sense) = 0;
972 970
    virtual Sense _getSense() const = 0;
973 971

	
974 972
    virtual void _clear() = 0;
975 973

	
976 974
    virtual const char* _solverName() const = 0;
977 975

	
978 976
    //Own protected stuff
979 977

	
980 978
    //Constant component of the objective function
981 979
    Value obj_const_comp;
982 980

	
983 981
    LpBase() : rows(), cols(), obj_const_comp(0) {}
984 982

	
985 983
  public:
986 984

	
987 985
    /// Virtual destructor
988 986
    virtual ~LpBase() {}
989 987

	
990
    ///Creates a new LP problem
991
    LpBase* newSolver() {return _newSolver();}
992
    ///Makes a copy of the LP problem
993
    LpBase* cloneSolver() {return _cloneSolver();}
994

	
995 988
    ///Gives back the name of the solver.
996 989
    const char* solverName() const {return _solverName();}
997 990

	
998 991
    ///\name Build up and modify the LP
999 992

	
1000 993
    ///@{
1001 994

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

	
1005 998
    ///\brief Adds several new columns (i.e variables) at once
1006 999
    ///
1007 1000
    ///This magic function takes a container as its argument and fills
1008 1001
    ///its elements with new columns (i.e. variables)
1009 1002
    ///\param t can be
1010 1003
    ///- a standard STL compatible iterable container with
1011 1004
    ///\ref Col as its \c values_type like
1012 1005
    ///\code
1013 1006
    ///std::vector<LpBase::Col>
1014 1007
    ///std::list<LpBase::Col>
1015 1008
    ///\endcode
1016 1009
    ///- a standard STL compatible iterable container with
1017 1010
    ///\ref Col as its \c mapped_type like
1018 1011
    ///\code
1019 1012
    ///std::map<AnyType,LpBase::Col>
1020 1013
    ///\endcode
1021 1014
    ///- an iterable lemon \ref concepts::WriteMap "write map" like
1022 1015
    ///\code
1023 1016
    ///ListGraph::NodeMap<LpBase::Col>
1024 1017
    ///ListGraph::ArcMap<LpBase::Col>
1025 1018
    ///\endcode
1026 1019
    ///\return The number of the created column.
1027 1020
#ifdef DOXYGEN
1028 1021
    template<class T>
1029 1022
    int addColSet(T &t) { return 0;}
1030 1023
#else
1031 1024
    template<class T>
1032 1025
    typename enable_if<typename T::value_type::LpCol,int>::type
1033 1026
    addColSet(T &t,dummy<0> = 0) {
1034 1027
      int s=0;
1035 1028
      for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
1036 1029
      return s;
1037 1030
    }
1038 1031
    template<class T>
1039 1032
    typename enable_if<typename T::value_type::second_type::LpCol,
1040 1033
                       int>::type
1041 1034
    addColSet(T &t,dummy<1> = 1) {
1042 1035
      int s=0;
... ...
@@ -1776,96 +1769,101 @@
1776 1769
    /// The problem types for primal and dual problems
1777 1770
    enum ProblemType {
1778 1771
      ///Feasible solution hasn't been found (but may exist).
1779 1772
      UNDEFINED = 0,
1780 1773
      ///The problem has no feasible solution
1781 1774
      INFEASIBLE = 1,
1782 1775
      ///Feasible solution found
1783 1776
      FEASIBLE = 2,
1784 1777
      ///Optimal solution exists and found
1785 1778
      OPTIMAL = 3,
1786 1779
      ///The cost function is unbounded
1787 1780
      UNBOUNDED = 4
1788 1781
    };
1789 1782

	
1790 1783
    ///The basis status of variables
1791 1784
    enum VarStatus {
1792 1785
      /// The variable is in the basis
1793 1786
      BASIC, 
1794 1787
      /// The variable is free, but not basic
1795 1788
      FREE,
1796 1789
      /// The variable has active lower bound 
1797 1790
      LOWER,
1798 1791
      /// The variable has active upper bound
1799 1792
      UPPER,
1800 1793
      /// The variable is non-basic and fixed
1801 1794
      FIXED
1802 1795
    };
1803 1796

	
1804 1797
  protected:
1805 1798

	
1806 1799
    virtual SolveExitStatus _solve() = 0;
1807 1800

	
1808 1801
    virtual Value _getPrimal(int i) const = 0;
1809 1802
    virtual Value _getDual(int i) const = 0;
1810 1803

	
1811 1804
    virtual Value _getPrimalRay(int i) const = 0;
1812 1805
    virtual Value _getDualRay(int i) const = 0;
1813 1806

	
1814 1807
    virtual Value _getPrimalValue() const = 0;
1815 1808

	
1816 1809
    virtual VarStatus _getColStatus(int i) const = 0;
1817 1810
    virtual VarStatus _getRowStatus(int i) const = 0;
1818 1811

	
1819 1812
    virtual ProblemType _getPrimalType() const = 0;
1820 1813
    virtual ProblemType _getDualType() const = 0;
1821 1814

	
1822 1815
  public:
1823 1816

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

	
1824 1822
    ///\name Solve the LP
1825 1823

	
1826 1824
    ///@{
1827 1825

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

	
1835 1833
    ///@}
1836 1834

	
1837 1835
    ///\name Obtain the solution
1838 1836

	
1839 1837
    ///@{
1840 1838

	
1841 1839
    /// The type of the primal problem
1842 1840
    ProblemType primalType() const {
1843 1841
      return _getPrimalType();
1844 1842
    }
1845 1843

	
1846 1844
    /// The type of the dual problem
1847 1845
    ProblemType dualType() const {
1848 1846
      return _getDualType();
1849 1847
    }
1850 1848

	
1851 1849
    /// Return the primal value of the column
1852 1850

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

	
1857 1855
    /// Return the primal value of the expression
1858 1856

	
1859 1857
    /// Return the primal value of the expression, i.e. the dot
1860 1858
    /// product of the primal solution and the expression.
1861 1859
    /// \pre The problem is solved.
1862 1860
    Value primal(const Expr& e) const {
1863 1861
      double res = *e;
1864 1862
      for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
1865 1863
        res += *c * primal(c);
1866 1864
      }
1867 1865
      return res;
1868 1866
    }
1869 1867
    /// Returns a component of the primal ray
1870 1868
    
1871 1869
    /// The primal ray is solution of the modified primal problem,
... ...
@@ -1890,191 +1888,182 @@
1890 1888
    /// Return the dual value of the dual expression
1891 1889

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

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

	
1918 1916
    /// Return the basis status of the column
1919 1917

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

	
1923 1921
    /// Return the basis status of the row
1924 1922

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

	
1928 1926
    ///The value of the objective function
1929 1927

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

	
1938
    LpSolver* newSolver() {return _newSolver();}
1939
    LpSolver* cloneSolver() {return _cloneSolver();}
1940

	
1941 1936
  protected:
1942 1937

	
1943
    virtual LpSolver* _newSolver() const = 0;
1944
    virtual LpSolver* _cloneSolver() const = 0;
1945 1938
  };
1946 1939

	
1947 1940

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

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

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

	
1978 1976
    ///\name Solve the MIP
1979 1977

	
1980 1978
    ///@{
1981 1979

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

	
1989 1987
    ///@}
1990 1988

	
1991 1989
    ///\name Setting column type
1992 1990
    ///@{
1993 1991

	
1994 1992
    ///Possible variable (column) types (e.g. real, integer, binary etc.)
1995 1993
    enum ColTypes {
1996 1994
      ///Continuous variable (default)
1997 1995
      REAL = 0,
1998 1996
      ///Integer variable
1999 1997
      INTEGER = 1
2000 1998
    };
2001 1999

	
2002 2000
    ///Sets the type of the given column to the given type
2003 2001

	
2004 2002
    ///Sets the type of the given column to the given type.
2005 2003
    ///
2006 2004
    void colType(Col c, ColTypes col_type) {
2007 2005
      _setColType(cols(id(c)),col_type);
2008 2006
    }
2009 2007

	
2010 2008
    ///Gives back the type of the column.
2011 2009

	
2012 2010
    ///Gives back the type of the column.
2013 2011
    ///
2014 2012
    ColTypes colType(Col c) const {
2015 2013
      return _getColType(cols(id(c)));
2016 2014
    }
2017 2015
    ///@}
2018 2016

	
2019 2017
    ///\name Obtain the solution
2020 2018

	
2021 2019
    ///@{
2022 2020

	
2023 2021
    /// The type of the MIP problem
2024 2022
    ProblemType type() const {
2025 2023
      return _getType();
2026 2024
    }
2027 2025

	
2028 2026
    /// Return the value of the row in the solution
2029 2027

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

	
2034 2032
    /// Return the value of the expression in the solution
2035 2033

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

	
2056 2054
  protected:
2057 2055

	
2058 2056
    virtual SolveExitStatus _solve() = 0;
2059 2057
    virtual ColTypes _getColType(int col) const = 0;
2060 2058
    virtual void _setColType(int col, ColTypes col_type) = 0;
2061 2059
    virtual ProblemType _getType() const = 0;
2062 2060
    virtual Value _getSol(int i) const = 0;
2063 2061
    virtual Value _getSolValue() const = 0;
2064 2062

	
2065
  public:
2066

	
2067
    MipSolver* newSolver() {return _newSolver();}
2068
    MipSolver* cloneSolver() {return _cloneSolver();}
2069

	
2070
  protected:
2071

	
2072
    virtual MipSolver* _newSolver() const = 0;
2073
    virtual MipSolver* _cloneSolver() const = 0;
2074 2063
  };
2075 2064

	
2076 2065

	
2077 2066

	
2078 2067
} //namespace lemon
2079 2068

	
2080 2069
#endif //LEMON_LP_BASE_H
Ignore white space 6 line context
... ...
@@ -60,75 +60,75 @@
60 60
  void SkeletonSolverBase::_setColUpperBound(int, Value) {}
61 61
  SkeletonSolverBase::Value SkeletonSolverBase::_getColUpperBound(int) const
62 62
  {  return 0; }
63 63

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
133 133
} //namespace lemon
134 134

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

	
19 19
#ifndef LEMON_LP_SKELETON_H
20 20
#define LEMON_LP_SKELETON_H
21 21

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

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

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

	
32 38
  protected:
33 39

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

	
37 43
    /// \e
38 44
    virtual int _addCol();
39 45
    /// \e
40 46
    virtual int _addRow();
41 47
    /// \e
42 48
    virtual void _eraseCol(int i);
43 49
    /// \e
44 50
    virtual void _eraseRow(int i);
45 51

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

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

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

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

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

	
75 81
    /// The lower bound of a variable (column) have to be given by an
76 82
    /// extended number of type Value, i.e. a finite number of type
... ...
@@ -91,139 +97,141 @@
91 97

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

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

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

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

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

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

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

	
129 135
    ///\e
130 136
    virtual void _setSense(Sense);
131 137
    ///\e
132 138
    virtual Sense _getSense() const;
133 139

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

	
137 143
  };
138 144

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

	
142 150
  ///\ingroup lp_group
143
  class LpSkeleton : public SkeletonSolverBase, public LpSolver {
151
  class LpSkeleton : public LpSolver, public SkeletonSolverBase {
144 152
  public:
145
    LpSkeleton() : SkeletonSolverBase(), LpSolver() {}
146

	
153
    ///\e
154
    LpSkeleton() : LpSolver(), SkeletonSolverBase() {}
155
    ///\e
156
    virtual LpSkeleton* newSolver() const;
157
    ///\e
158
    virtual LpSkeleton* cloneSolver() const;
147 159
  protected:
148 160

	
149 161
    ///\e
150 162
    virtual SolveExitStatus _solve();
151 163

	
152 164
    ///\e
153 165
    virtual Value _getPrimal(int i) const;
154 166
    ///\e
155 167
    virtual Value _getDual(int i) const;
156 168

	
157 169
    ///\e
158 170
    virtual Value _getPrimalValue() const;
159 171

	
160 172
    ///\e
161 173
    virtual Value _getPrimalRay(int i) const;
162 174
    ///\e
163 175
    virtual Value _getDualRay(int i) const;
164 176

	
165 177
    ///\e
166 178
    virtual ProblemType _getPrimalType() const;
167 179
    ///\e
168 180
    virtual ProblemType _getDualType() const;
169 181

	
170 182
    ///\e
171 183
    virtual VarStatus _getColStatus(int i) const;
172 184
    ///\e
173 185
    virtual VarStatus _getRowStatus(int i) const;
174 186

	
175 187
    ///\e
176
    virtual LpSkeleton* _newSolver() const;
177
    ///\e
178
    virtual LpSkeleton* _cloneSolver() const;
179
    ///\e
180 188
    virtual const char* _solverName() const;
181 189

	
182 190
  };
183 191

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

	
192 206
  protected:
193 207
    ///\e
194 208

	
195 209
    ///\bug Wrong interface
196 210
    ///
197 211
    virtual SolveExitStatus _solve();
198 212

	
199 213
    ///\e
200 214

	
201 215
    ///\bug Wrong interface
202 216
    ///
203 217
    virtual Value _getSol(int i) const;
204 218

	
205 219
    ///\e
206 220

	
207 221
    ///\bug Wrong interface
208 222
    ///
209 223
    virtual Value _getSolValue() const;
210 224

	
211 225
    ///\e
212 226

	
213 227
    ///\bug Wrong interface
214 228
    ///
215 229
    virtual ProblemType _getType() const;
216 230

	
217 231
    ///\e
218
    virtual MipSkeleton* _newSolver() const;
219

	
220
    ///\e
221
    virtual MipSkeleton* _cloneSolver() const;
222
    ///\e
223 232
    virtual const char* _solverName() const;
224

	
225 233
  };
226 234

	
227 235
} //namespace lemon
228 236

	
229 237
#endif
Ignore white space 6 line context
... ...
@@ -9,102 +9,102 @@
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

	
24 24

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

	
29 29
  SoplexLp::SoplexLp() {
30 30
    soplex = new soplex::SoPlex;
31 31
  }
32 32

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

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

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

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

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

	
50 50
  }
51 51

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

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

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

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

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

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

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

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

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

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

	
91 91

	
92 92
  void SoplexLp::_eraseCol(int i) {
93 93
    soplex->removeCol(i);
94 94
    _col_names_ref.erase(_col_names[i]);
95 95
    _col_names[i] = _col_names.back();
96 96
    _col_names_ref[_col_names.back()] = i;
97 97
    _col_names.pop_back();
98 98
  }
99 99

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

	
108 108
  void SoplexLp::_eraseColId(int i) {
109 109
    cols.eraseIndex(i);
110 110
    cols.relocateIndex(i, cols.maxIndex());
Ignore white space 6 line context
... ...
@@ -28,102 +28,103 @@
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
    /// \e
77
    virtual SoplexLp* newSolver() const;
78
    /// \e
79
    virtual SoplexLp* cloneSolver() const;
76 80

	
77 81
  protected:
78 82

	
79
    virtual SoplexLp* _newSolver() const;
80
    virtual SoplexLp* _cloneSolver() const;
81

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
129 130
    virtual SolveExitStatus _solve();
Ignore white space 6 line context
... ...
@@ -152,147 +152,153 @@
152 152
    c = (e  == f  );
153 153
    c = (e  == 2.2);
154 154
    c = (e  == 2  );
155 155
    c = (e  == p1 );
156 156
    c = (2.2== f  );
157 157
    c = (2  == f  );
158 158
    c = (p1 == f  );
159 159
    //c = (p1 == p2 );
160 160
    c = (p1 == 2.2);
161 161
    c = (p1 == 2  );
162 162
    c = (2.2== p2 );
163 163
    c = (2  == p2 );
164 164

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

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

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

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

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

	
184 184
    std::ostringstream buf;
185 185

	
186 186

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

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

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

	
201 206
  }
202 207

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

	
208 213
    e[p1]=2;
209 214
    e[p1]+=2;
210 215
    e[p1]-=2;
211 216

	
212 217
    e=p1;
213 218
    e=f;
214 219

	
215 220
    e+=p1;
216 221
    e+=f;
217 222

	
218 223
    e-=p1;
219 224
    e-=f;
220 225

	
221 226
    e*=2;
222 227
    e*=2.2;
223 228
    e/=2;
224 229
    e/=2.2;
225 230

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

	
236 241
}
237 242

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

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

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

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

	
255 261
void aTest(LpSolver & lp)
256 262
{
257 263
  typedef LpSolver LP;
258 264

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

	
261 267
  typedef LpSolver::Row Row;
262 268
  typedef LpSolver::Col Col;
263 269

	
264 270

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

	
268 274

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

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

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

	
298 304
  lp.row(upright, x1+x2 <=1);
... ...
@@ -310,94 +316,111 @@
310 316
  check(clp->sense() == clp->MAX,"This is a maximization!");
311 317
  check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
312 318
  //  std::cout<<lp.colLowerBound(x1)<<std::endl;
313 319
  check(clp->colLowerBound(x1)==0,
314 320
        "The lower bound for variable x1 should be 0.");
315 321
  check(clp->colUpperBound(x1)==LpSolver::INF,
316 322
        "The upper bound for variable x1 should be infty.");
317 323

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

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

	
329 335
  delete clp;
330 336

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

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

	
341 347
  //Vertex (-1,0) instead of (0,0)
342 348
  lp.colLowerBound(x1, -LpSolver::INF);
343 349
  expected_opt=-1;
344 350
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
345 351

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

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

	
356 362
}
357 363

	
364
template<class LP>
365
void cloneTest()
366
{
367
  //Test for clone/new
368
  
369
  LP* lp = new LP();
370
  LP* lpnew = lp->newSolver();
371
  LP* lpclone = lp->cloneSolver();
372
  delete lp;
373
  delete lpnew;
374
  delete lpclone;
375
}
376

	
358 377
int main()
359 378
{
360 379
  LpSkeleton lp_skel;
361 380
  lpTest(lp_skel);
362 381

	
363 382
#ifdef HAVE_GLPK
364 383
  {
365 384
    GlpkLp lp_glpk1,lp_glpk2;
366 385
    lpTest(lp_glpk1);
367 386
    aTest(lp_glpk2);
387
    cloneTest<GlpkLp>();
368 388
  }
369 389
#endif
370 390

	
371 391
#ifdef HAVE_CPLEX
372 392
  try {
373 393
    CplexLp lp_cplex1,lp_cplex2;
374 394
    lpTest(lp_cplex1);
375 395
    aTest(lp_cplex2);
376 396
  } catch (CplexEnv::LicenseError& error) {
377 397
#ifdef LEMON_FORCE_CPLEX_CHECK
378 398
    check(false, error.what());
379 399
#else
380 400
    std::cerr << error.what() << std::endl;
381 401
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
382 402
#endif
383 403
  }
404
    cloneTest<CplexLp>();
384 405
#endif
385 406

	
386 407
#ifdef HAVE_SOPLEX
387 408
  {
388 409
    SoplexLp lp_soplex1,lp_soplex2;
389 410
    lpTest(lp_soplex1);
390 411
    aTest(lp_soplex2);
412
    cloneTest<SoplexLp>();
391 413
  }
392 414
#endif
393 415

	
394 416
#ifdef HAVE_CLP
395 417
  {
396 418
    ClpLp lp_clp1,lp_clp2;
397 419
    lpTest(lp_clp1);
398 420
    aTest(lp_clp2);
421
    cloneTest<ClpLp>();
399 422
  }
400 423
#endif
401 424

	
402 425
  return 0;
403 426
}
Ignore white space 96 line context
... ...
@@ -61,76 +61,89 @@
61 61

	
62 62

	
63 63
  typedef MipSolver::Row Row;
64 64
  typedef MipSolver::Col Col;
65 65

	
66 66

	
67 67

	
68 68
  Col x1 = mip.addCol();
69 69
  Col x2 = mip.addCol();
70 70

	
71 71

	
72 72
  //Objective function
73 73
  mip.obj(x1);
74 74

	
75 75
  mip.max();
76 76

	
77 77

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

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

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

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

	
94 94
  //Restrict x2 to integer
95 95
  mip.colType(x2,MipSolver::INTEGER);
96 96
  expected_opt=1.0/2.0;
97 97
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
98 98

	
99 99

	
100 100
  //Restrict both to integer
101 101
  mip.colType(x1,MipSolver::INTEGER);
102 102
  expected_opt=0;
103 103
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
104 104

	
105 105

	
106 106

	
107 107
}
108 108

	
109
template<class MIP>
110
void cloneTest()
111
{
112
  
113
  MIP* mip = new MIP();
114
  MIP* mipnew = mip->newSolver();
115
  MIP* mipclone = mip->cloneSolver();
116
  delete mip;
117
  delete mipnew;
118
  delete mipclone;
119
}
109 120

	
110 121
int main()
111 122
{
112 123

	
113 124
#ifdef HAVE_GLPK
114 125
  {
115 126
    GlpkMip mip1;
116 127
    aTest(mip1);
128
    cloneTest<GlpkMip>();
117 129
  }
118 130
#endif
119 131

	
120 132
#ifdef HAVE_CPLEX
121 133
  try {
122 134
    CplexMip mip2;
123 135
    aTest(mip2);
124 136
  } catch (CplexEnv::LicenseError& error) {
125 137
#ifdef LEMON_FORCE_CPLEX_CHECK
126 138
    check(false, error.what());
127 139
#else
128 140
    std::cerr << error.what() << std::endl;
129 141
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
130 142
#endif
131 143
  }
144
  cloneTest<CplexMip>();
132 145
#endif
133 146

	
134 147
  return 0;
135 148

	
136 149
}
0 comments (0 inline)