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
... ...
@@ -53,18 +53,18 @@
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

	
Ignore white space 6 line context
... ...
@@ -53,25 +53,27 @@
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);
Ignore white space 6 line context
... ...
@@ -448,14 +448,14 @@
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();
... ...
@@ -820,14 +820,14 @@
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
Ignore white space 12 line context
... ...
@@ -157,23 +157,28 @@
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

	
... ...
@@ -183,15 +188,12 @@
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;
... ...
@@ -219,13 +221,13 @@
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
Ignore white space 6 line context
... ...
@@ -531,14 +531,14 @@
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();
... ...
@@ -937,14 +937,14 @@
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
  }
Ignore white space 6 line context
... ...
@@ -116,32 +116,34 @@
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

	
... ...
@@ -200,25 +202,25 @@
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();
Ignore white space 6 line context
... ...
@@ -915,14 +915,12 @@
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); }
... ...
@@ -984,17 +982,12 @@
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
    ///@{
... ...
@@ -1818,12 +1811,17 @@
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
    ///
... ...
@@ -1932,19 +1930,14 @@
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
... ...
@@ -1972,12 +1965,17 @@
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
    ///
... ...
@@ -2059,21 +2057,12 @@
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

	
Ignore white space 6 line context
... ...
@@ -102,16 +102,16 @@
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; }
... ...
@@ -119,16 +119,16 @@
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
... ...
@@ -19,16 +19,22 @@
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()
... ...
@@ -133,20 +139,26 @@
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
... ...
@@ -170,27 +182,29 @@
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
    ///
... ...
@@ -212,18 +226,12 @@
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
... ...
@@ -51,18 +51,18 @@
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

	
Ignore white space 6 line context
... ...
@@ -70,18 +70,19 @@
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);
Ignore white space 6 line context
... ...
@@ -194,12 +194,17 @@
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,
... ...
@@ -244,13 +249,14 @@
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
{
... ...
@@ -352,22 +358,36 @@
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;
... ...
@@ -378,26 +398,29 @@
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
... ...
@@ -103,20 +103,32 @@
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;
... ...
@@ -126,11 +138,12 @@
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)