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
... ...
@@ -47,30 +47,30 @@
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() {
Ignore white space 6 line context
... ...
@@ -47,37 +47,39 @@
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;
Ignore white space 6 line context
... ...
@@ -442,26 +442,26 @@
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
... ...
@@ -814,26 +814,26 @@
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);
Ignore white space 6 line context
... ...
@@ -151,53 +151,55 @@
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;
... ...
@@ -213,25 +215,25 @@
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

	
Ignore white space 6 line context
... ...
@@ -525,26 +525,26 @@
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

	
... ...
@@ -931,22 +931,22 @@
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
... ...
@@ -110,44 +110,46 @@
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;
... ...
@@ -194,37 +196,37 @@
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 {
Ignore white space 6 line context
... ...
@@ -909,26 +909,24 @@
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;
... ...
@@ -978,29 +976,24 @@
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
    ///
... ...
@@ -1812,24 +1805,29 @@
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
    ///@}
... ...
@@ -1926,31 +1924,26 @@
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
... ...
@@ -1966,24 +1959,29 @@
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
    ///@}
... ...
@@ -2053,28 +2051,19 @@
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 24 line context
... ...
@@ -96,39 +96,39 @@
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
... ...
@@ -13,28 +13,34 @@
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();
... ...
@@ -127,32 +133,38 @@
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;
... ...
@@ -164,39 +176,41 @@
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
    ///
... ...
@@ -206,24 +220,18 @@
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
... ...
@@ -45,30 +45,30 @@
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

	
Ignore white space 6 line context
... ...
@@ -64,30 +64,31 @@
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;
Ignore white space 6 line context
... ...
@@ -188,24 +188,29 @@
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

	
... ...
@@ -238,25 +243,26 @@
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;
... ...
@@ -346,58 +352,75 @@
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 6 line context
... ...
@@ -97,40 +97,53 @@
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)