# HG changeset patch # User Alpar Juttner # Date 2009-02-26 08:39:16 # Node ID 9db62975c32bb931e080e1581a68563939c7eb6a # Parent 547e966b3b293bc27cceb51512f60f3d854b2b6f 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 diff --git a/lemon/clp.cc b/lemon/clp.cc --- a/lemon/clp.cc +++ b/lemon/clp.cc @@ -56,12 +56,12 @@ } } - ClpLp* ClpLp::_newSolver() const { + ClpLp* ClpLp::newSolver() const { ClpLp* newlp = new ClpLp; return newlp; } - ClpLp* ClpLp::_cloneSolver() const { + ClpLp* ClpLp::cloneSolver() const { ClpLp* copylp = new ClpLp(*this); return copylp; } diff --git a/lemon/clp.h b/lemon/clp.h --- a/lemon/clp.h +++ b/lemon/clp.h @@ -56,6 +56,11 @@ /// \e ~ClpLp(); + /// \e + virtual ClpLp* newSolver() const; + /// \e + virtual ClpLp* cloneSolver() const; + protected: mutable double* _primal_ray; @@ -66,9 +71,6 @@ protected: - virtual ClpLp* _newSolver() const; - virtual ClpLp* _cloneSolver() const; - virtual const char* _solverName() const; virtual int _addCol(); diff --git a/lemon/cplex.cc b/lemon/cplex.cc --- a/lemon/cplex.cc +++ b/lemon/cplex.cc @@ -451,8 +451,8 @@ CplexLp::~CplexLp() {} - CplexLp* CplexLp::_newSolver() const { return new CplexLp; } - CplexLp* CplexLp::_cloneSolver() const {return new CplexLp(*this); } + CplexLp* CplexLp::newSolver() const { return new CplexLp; } + CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); } const char* CplexLp::_solverName() const { return "CplexLp"; } @@ -823,8 +823,8 @@ CplexMip::~CplexMip() {} - CplexMip* CplexMip::_newSolver() const { return new CplexMip; } - CplexMip* CplexMip::_cloneSolver() const {return new CplexMip(*this); } + CplexMip* CplexMip::newSolver() const { return new CplexMip; } + CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); } const char* CplexMip::_solverName() const { return "CplexMip"; } diff --git a/lemon/cplex.h b/lemon/cplex.h --- a/lemon/cplex.h +++ b/lemon/cplex.h @@ -160,7 +160,7 @@ /// /// This class implements an interface for the CPLEX LP solver. ///\ingroup lp_group - class CplexLp : public CplexBase, public LpSolver { + class CplexLp : public LpSolver, public CplexBase { public: /// \e CplexLp(); @@ -171,6 +171,11 @@ /// \e virtual ~CplexLp(); + /// \e + virtual CplexLp* cloneSolver() const; + /// \e + virtual CplexLp* newSolver() const; + private: // these values cannot retrieved element by element @@ -186,9 +191,6 @@ protected: - virtual CplexLp* _cloneSolver() const; - virtual CplexLp* _newSolver() const; - virtual const char* _solverName() const; virtual SolveExitStatus _solve(); @@ -222,7 +224,7 @@ /// /// This class implements an interface for the CPLEX MIP solver. ///\ingroup lp_group - class CplexMip : public CplexBase, public MipSolver { + class CplexMip : public MipSolver, public CplexBase { public: /// \e CplexMip(); diff --git a/lemon/glpk.cc b/lemon/glpk.cc --- a/lemon/glpk.cc +++ b/lemon/glpk.cc @@ -534,8 +534,8 @@ messageLevel(MESSAGE_NO_OUTPUT); } - GlpkLp* GlpkLp::_newSolver() const { return new GlpkLp; } - GlpkLp* GlpkLp::_cloneSolver() const { return new GlpkLp(*this); } + GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; } + GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); } const char* GlpkLp::_solverName() const { return "GlpkLp"; } @@ -940,8 +940,8 @@ return glp_mip_obj_val(lp); } - GlpkMip* GlpkMip::_newSolver() const { return new GlpkMip; } - GlpkMip* GlpkMip::_cloneSolver() const {return new GlpkMip(*this); } + GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; } + GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); } const char* GlpkMip::_solverName() const { return "GlpkMip"; } diff --git a/lemon/glpk.h b/lemon/glpk.h --- a/lemon/glpk.h +++ b/lemon/glpk.h @@ -119,7 +119,7 @@ /// /// This class implements an interface for the GLPK LP solver. ///\ingroup lp_group - class GlpkLp : public GlpkBase, public LpSolver { + class GlpkLp : public LpSolver, public GlpkBase { public: ///\e @@ -127,6 +127,11 @@ ///\e GlpkLp(const GlpkLp&); + ///\e + virtual GlpkLp* cloneSolver() const; + ///\e + virtual GlpkLp* newSolver() const; + private: mutable std::vector _primal_ray; @@ -136,9 +141,6 @@ protected: - virtual GlpkLp* _cloneSolver() const; - virtual GlpkLp* _newSolver() const; - virtual const char* _solverName() const; virtual SolveExitStatus _solve(); @@ -203,7 +205,7 @@ /// /// This class implements an interface for the GLPK MIP solver. ///\ingroup lp_group - class GlpkMip : public GlpkBase, public MipSolver { + class GlpkMip : public MipSolver, public GlpkBase { public: ///\e @@ -211,11 +213,11 @@ ///\e GlpkMip(const GlpkMip&); + virtual GlpkMip* cloneSolver() const; + virtual GlpkMip* newSolver() const; + protected: - virtual GlpkMip* _cloneSolver() const; - virtual GlpkMip* _newSolver() const; - virtual const char* _solverName() const; virtual ColTypes _getColType(int col) const; diff --git a/lemon/lp_base.h b/lemon/lp_base.h --- a/lemon/lp_base.h +++ b/lemon/lp_base.h @@ -918,8 +918,6 @@ protected: //Abstract virtual functions - virtual LpBase* _newSolver() const = 0; - virtual LpBase* _cloneSolver() const = 0; virtual int _addColId(int col) { return cols.addIndex(col); } virtual int _addRowId(int row) { return rows.addIndex(row); } @@ -987,11 +985,6 @@ /// Virtual destructor virtual ~LpBase() {} - ///Creates a new LP problem - LpBase* newSolver() {return _newSolver();} - ///Makes a copy of the LP problem - LpBase* cloneSolver() {return _cloneSolver();} - ///Gives back the name of the solver. const char* solverName() const {return _solverName();} @@ -1821,6 +1814,11 @@ public: + ///Allocate a new LP problem instance + virtual LpSolver* newSolver() const = 0; + ///Make a copy of the LP problem + virtual LpSolver* cloneSolver() const = 0; + ///\name Solve the LP ///@{ @@ -1935,13 +1933,8 @@ Value primal() const { return _getPrimalValue()+obj_const_comp;} ///@} - LpSolver* newSolver() {return _newSolver();} - LpSolver* cloneSolver() {return _cloneSolver();} - protected: - virtual LpSolver* _newSolver() const = 0; - virtual LpSolver* _cloneSolver() const = 0; }; @@ -1975,6 +1968,11 @@ UNBOUNDED = 4 }; + ///Allocate a new MIP problem instance + virtual MipSolver* newSolver() const = 0; + ///Make a copy of the MIP problem + virtual MipSolver* cloneSolver() const = 0; + ///\name Solve the MIP ///@{ @@ -2062,15 +2060,6 @@ virtual Value _getSol(int i) const = 0; virtual Value _getSolValue() const = 0; - public: - - MipSolver* newSolver() {return _newSolver();} - MipSolver* cloneSolver() {return _cloneSolver();} - - protected: - - virtual MipSolver* _newSolver() const = 0; - virtual MipSolver* _cloneSolver() const = 0; }; diff --git a/lemon/lp_skeleton.cc b/lemon/lp_skeleton.cc --- a/lemon/lp_skeleton.cc +++ b/lemon/lp_skeleton.cc @@ -105,10 +105,10 @@ LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const { return BASIC; } - LpSkeleton* LpSkeleton::_newSolver() const + LpSkeleton* LpSkeleton::newSolver() const { return static_cast(0); } - LpSkeleton* LpSkeleton::_cloneSolver() const + LpSkeleton* LpSkeleton::cloneSolver() const { return static_cast(0); } const char* LpSkeleton::_solverName() const { return "LpSkeleton"; } @@ -122,10 +122,10 @@ MipSkeleton::ProblemType MipSkeleton::_getType() const { return UNDEFINED; } - MipSkeleton* MipSkeleton::_newSolver() const + MipSkeleton* MipSkeleton::newSolver() const { return static_cast(0); } - MipSkeleton* MipSkeleton::_cloneSolver() const + MipSkeleton* MipSkeleton::cloneSolver() const { return static_cast(0); } const char* MipSkeleton::_solverName() const { return "MipSkeleton"; } diff --git a/lemon/lp_skeleton.h b/lemon/lp_skeleton.h --- a/lemon/lp_skeleton.h +++ b/lemon/lp_skeleton.h @@ -22,10 +22,16 @@ #include ///\file -///\brief A skeleton file to implement LP solver interfaces +///\brief Skeleton file to implement LP/MIP solver interfaces +/// +///The classes in this file do nothing, but they can serve as skeletons when +///implementing an interface to new solvers. namespace lemon { - ///A skeleton class to implement LP solver interfaces + ///A skeleton class to implement LP/MIP solver base interface + + ///This class does nothing, but it can serve as a skeleton when + ///implementing an interface to new solvers. class SkeletonSolverBase : public virtual LpBase { int col_num,row_num; @@ -136,14 +142,20 @@ }; - /// \brief Interface for a skeleton LP solver + /// \brief Skeleton class for an LP solver interface /// - /// This class implements an interface for a skeleton LP solver. + ///This class does nothing, but it can serve as a skeleton when + ///implementing an interface to new solvers. + ///\ingroup lp_group - class LpSkeleton : public SkeletonSolverBase, public LpSolver { + class LpSkeleton : public LpSolver, public SkeletonSolverBase { public: - LpSkeleton() : SkeletonSolverBase(), LpSolver() {} - + ///\e + LpSkeleton() : LpSolver(), SkeletonSolverBase() {} + ///\e + virtual LpSkeleton* newSolver() const; + ///\e + virtual LpSkeleton* cloneSolver() const; protected: ///\e @@ -173,21 +185,23 @@ virtual VarStatus _getRowStatus(int i) const; ///\e - virtual LpSkeleton* _newSolver() const; - ///\e - virtual LpSkeleton* _cloneSolver() const; - ///\e virtual const char* _solverName() const; }; - /// \brief Interface for a skeleton MIP solver + /// \brief Skeleton class for a MIP solver interface /// - /// This class implements an interface for a skeleton MIP solver. + ///This class does nothing, but it can serve as a skeleton when + ///implementing an interface to new solvers. ///\ingroup lp_group - class MipSkeleton : public SkeletonSolverBase, public MipSolver { + class MipSkeleton : public MipSolver, public SkeletonSolverBase { public: - MipSkeleton() : SkeletonSolverBase(), MipSolver() {} + ///\e + MipSkeleton() : MipSolver(), SkeletonSolverBase() {} + ///\e + virtual MipSkeleton* newSolver() const; + ///\e + virtual MipSkeleton* cloneSolver() const; protected: ///\e @@ -215,13 +229,7 @@ virtual ProblemType _getType() const; ///\e - virtual MipSkeleton* _newSolver() const; - - ///\e - virtual MipSkeleton* _cloneSolver() const; - ///\e virtual const char* _solverName() const; - }; } //namespace lemon diff --git a/lemon/soplex.cc b/lemon/soplex.cc --- a/lemon/soplex.cc +++ b/lemon/soplex.cc @@ -54,12 +54,12 @@ _dual_values.clear(); } - SoplexLp* SoplexLp::_newSolver() const { + SoplexLp* SoplexLp::newSolver() const { SoplexLp* newlp = new SoplexLp(); return newlp; } - SoplexLp* SoplexLp::_cloneSolver() const { + SoplexLp* SoplexLp::cloneSolver() const { SoplexLp* newlp = new SoplexLp(*this); return newlp; } diff --git a/lemon/soplex.h b/lemon/soplex.h --- a/lemon/soplex.h +++ b/lemon/soplex.h @@ -73,12 +73,13 @@ SoplexLp(const SoplexLp&); /// \e ~SoplexLp(); + /// \e + virtual SoplexLp* newSolver() const; + /// \e + virtual SoplexLp* cloneSolver() const; protected: - virtual SoplexLp* _newSolver() const; - virtual SoplexLp* _cloneSolver() const; - virtual const char* _solverName() const; virtual int _addCol(); diff --git a/test/lp_test.cc b/test/lp_test.cc --- a/test/lp_test.cc +++ b/test/lp_test.cc @@ -197,6 +197,11 @@ buf << "Coeff. of p2 should be 0"; check(const_cast(e)[p2]==0, buf.str()); + //Test for clone/new + LP* lpnew = lp.newSolver(); + LP* lpclone = lp.cloneSolver(); + delete lpnew; + delete lpclone; } @@ -247,7 +252,8 @@ if (stat == LpSolver::OPTIMAL) { std::ostringstream sbuf; - sbuf << "Wrong optimal value: the right optimum is " << exp_opt; + sbuf << "Wrong optimal value (" << lp.primal() <<") with " + << lp.solverName() <<"\n the right optimum is " << exp_opt; check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str()); } } @@ -355,6 +361,19 @@ } +template +void cloneTest() +{ + //Test for clone/new + + LP* lp = new LP(); + LP* lpnew = lp->newSolver(); + LP* lpclone = lp->cloneSolver(); + delete lp; + delete lpnew; + delete lpclone; +} + int main() { LpSkeleton lp_skel; @@ -365,6 +384,7 @@ GlpkLp lp_glpk1,lp_glpk2; lpTest(lp_glpk1); aTest(lp_glpk2); + cloneTest(); } #endif @@ -381,6 +401,7 @@ std::cerr << "Cplex license check failed, lp check skipped" << std::endl; #endif } + cloneTest(); #endif #ifdef HAVE_SOPLEX @@ -388,6 +409,7 @@ SoplexLp lp_soplex1,lp_soplex2; lpTest(lp_soplex1); aTest(lp_soplex2); + cloneTest(); } #endif @@ -396,6 +418,7 @@ ClpLp lp_clp1,lp_clp2; lpTest(lp_clp1); aTest(lp_clp2); + cloneTest(); } #endif diff --git a/test/mip_test.cc b/test/mip_test.cc --- a/test/mip_test.cc +++ b/test/mip_test.cc @@ -106,6 +106,17 @@ } +template +void cloneTest() +{ + + MIP* mip = new MIP(); + MIP* mipnew = mip->newSolver(); + MIP* mipclone = mip->cloneSolver(); + delete mip; + delete mipnew; + delete mipclone; +} int main() { @@ -114,6 +125,7 @@ { GlpkMip mip1; aTest(mip1); + cloneTest(); } #endif @@ -129,6 +141,7 @@ std::cerr << "Cplex license check failed, lp check skipped" << std::endl; #endif } + cloneTest(); #endif return 0;