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 64 line context
... ...
@@ -27,70 +27,70 @@
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

	
Ignore white space 64 line context
... ...
@@ -27,77 +27,79 @@
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;
Ignore white space 64 line context
... ...
@@ -422,66 +422,66 @@
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;
... ...
@@ -794,66 +794,66 @@
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");
Ignore white space 64 line context
... ...
@@ -131,126 +131,128 @@
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 64 line context
... ...
@@ -505,66 +505,66 @@
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
    }
... ...
@@ -911,42 +911,42 @@
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 64 line context
... ...
@@ -90,161 +90,163 @@
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
    ///
Ignore white space 64 line context
... ...
@@ -889,66 +889,64 @@
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;
... ...
@@ -958,69 +956,64 @@
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.
... ...
@@ -1792,64 +1785,69 @@
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))); }
... ...
@@ -1906,104 +1904,104 @@
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

	
... ...
@@ -2033,48 +2031,39 @@
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 64 line context
... ...
@@ -76,59 +76,59 @@
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 64 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
... ...
@@ -107,123 +113,125 @@
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 64 line context
... ...
@@ -25,70 +25,70 @@
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]);
Ignore white space 64 line context
... ...
@@ -44,70 +44,71 @@
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;
Ignore white space 64 line context
... ...
@@ -168,115 +168,121 @@
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
... ...
@@ -326,78 +332,95 @@
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 64 line context
... ...
@@ -77,60 +77,73 @@
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)