Fix newSolver()/cloneSolver() API in LP tools + doc improvements (#230)
authorAlpar Juttner <alpar@cs.elte.hu>
Thu, 26 Feb 2009 07:39:16 +0000
changeset 5289db62975c32b
parent 527 547e966b3b29
child 529 89e29e22d479
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
lemon/clp.cc
lemon/clp.h
lemon/cplex.cc
lemon/cplex.h
lemon/glpk.cc
lemon/glpk.h
lemon/lp_base.h
lemon/lp_skeleton.cc
lemon/lp_skeleton.h
lemon/soplex.cc
lemon/soplex.h
test/lp_test.cc
test/mip_test.cc
     1.1 --- a/lemon/clp.cc	Thu Feb 26 09:39:02 2009 +0000
     1.2 +++ b/lemon/clp.cc	Thu Feb 26 07:39:16 2009 +0000
     1.3 @@ -56,12 +56,12 @@
     1.4      }
     1.5    }
     1.6  
     1.7 -  ClpLp* ClpLp::_newSolver() const {
     1.8 +  ClpLp* ClpLp::newSolver() const {
     1.9      ClpLp* newlp = new ClpLp;
    1.10      return newlp;
    1.11    }
    1.12  
    1.13 -  ClpLp* ClpLp::_cloneSolver() const {
    1.14 +  ClpLp* ClpLp::cloneSolver() const {
    1.15      ClpLp* copylp = new ClpLp(*this);
    1.16      return copylp;
    1.17    }
     2.1 --- a/lemon/clp.h	Thu Feb 26 09:39:02 2009 +0000
     2.2 +++ b/lemon/clp.h	Thu Feb 26 07:39:16 2009 +0000
     2.3 @@ -56,6 +56,11 @@
     2.4      /// \e
     2.5      ~ClpLp();
     2.6  
     2.7 +    /// \e
     2.8 +    virtual ClpLp* newSolver() const;
     2.9 +    /// \e
    2.10 +    virtual ClpLp* cloneSolver() const;
    2.11 +
    2.12    protected:
    2.13  
    2.14      mutable double* _primal_ray;
    2.15 @@ -66,9 +71,6 @@
    2.16  
    2.17    protected:
    2.18  
    2.19 -    virtual ClpLp* _newSolver() const;
    2.20 -    virtual ClpLp* _cloneSolver() const;
    2.21 -
    2.22      virtual const char* _solverName() const;
    2.23  
    2.24      virtual int _addCol();
     3.1 --- a/lemon/cplex.cc	Thu Feb 26 09:39:02 2009 +0000
     3.2 +++ b/lemon/cplex.cc	Thu Feb 26 07:39:16 2009 +0000
     3.3 @@ -451,8 +451,8 @@
     3.4  
     3.5    CplexLp::~CplexLp() {}
     3.6  
     3.7 -  CplexLp* CplexLp::_newSolver() const { return new CplexLp; }
     3.8 -  CplexLp* CplexLp::_cloneSolver() const {return new CplexLp(*this); }
     3.9 +  CplexLp* CplexLp::newSolver() const { return new CplexLp; }
    3.10 +  CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
    3.11  
    3.12    const char* CplexLp::_solverName() const { return "CplexLp"; }
    3.13  
    3.14 @@ -823,8 +823,8 @@
    3.15  
    3.16    CplexMip::~CplexMip() {}
    3.17  
    3.18 -  CplexMip* CplexMip::_newSolver() const { return new CplexMip; }
    3.19 -  CplexMip* CplexMip::_cloneSolver() const {return new CplexMip(*this); }
    3.20 +  CplexMip* CplexMip::newSolver() const { return new CplexMip; }
    3.21 +  CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
    3.22  
    3.23    const char* CplexMip::_solverName() const { return "CplexMip"; }
    3.24  
     4.1 --- a/lemon/cplex.h	Thu Feb 26 09:39:02 2009 +0000
     4.2 +++ b/lemon/cplex.h	Thu Feb 26 07:39:16 2009 +0000
     4.3 @@ -160,7 +160,7 @@
     4.4    ///
     4.5    /// This class implements an interface for the CPLEX LP solver.
     4.6    ///\ingroup lp_group
     4.7 -  class CplexLp : public CplexBase, public LpSolver {
     4.8 +  class CplexLp : public LpSolver, public CplexBase {
     4.9    public:
    4.10      /// \e
    4.11      CplexLp();
    4.12 @@ -171,6 +171,11 @@
    4.13      /// \e
    4.14      virtual ~CplexLp();
    4.15  
    4.16 +    /// \e
    4.17 +    virtual CplexLp* cloneSolver() const;
    4.18 +    /// \e
    4.19 +    virtual CplexLp* newSolver() const;
    4.20 +
    4.21    private:
    4.22  
    4.23      // these values cannot retrieved element by element
    4.24 @@ -186,9 +191,6 @@
    4.25  
    4.26    protected:
    4.27  
    4.28 -    virtual CplexLp* _cloneSolver() const;
    4.29 -    virtual CplexLp* _newSolver() const;
    4.30 -
    4.31      virtual const char* _solverName() const;
    4.32  
    4.33      virtual SolveExitStatus _solve();
    4.34 @@ -222,7 +224,7 @@
    4.35    ///
    4.36    /// This class implements an interface for the CPLEX MIP solver.
    4.37    ///\ingroup lp_group
    4.38 -  class CplexMip : public CplexBase, public MipSolver {
    4.39 +  class CplexMip : public MipSolver, public CplexBase {
    4.40    public:
    4.41      /// \e
    4.42      CplexMip();
     5.1 --- a/lemon/glpk.cc	Thu Feb 26 09:39:02 2009 +0000
     5.2 +++ b/lemon/glpk.cc	Thu Feb 26 07:39:16 2009 +0000
     5.3 @@ -534,8 +534,8 @@
     5.4      messageLevel(MESSAGE_NO_OUTPUT);
     5.5    }
     5.6  
     5.7 -  GlpkLp* GlpkLp::_newSolver() const { return new GlpkLp; }
     5.8 -  GlpkLp* GlpkLp::_cloneSolver() const { return new GlpkLp(*this); }
     5.9 +  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
    5.10 +  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
    5.11  
    5.12    const char* GlpkLp::_solverName() const { return "GlpkLp"; }
    5.13  
    5.14 @@ -940,8 +940,8 @@
    5.15      return glp_mip_obj_val(lp);
    5.16    }
    5.17  
    5.18 -  GlpkMip* GlpkMip::_newSolver() const { return new GlpkMip; }
    5.19 -  GlpkMip* GlpkMip::_cloneSolver() const {return new GlpkMip(*this); }
    5.20 +  GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; }
    5.21 +  GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); }
    5.22  
    5.23    const char* GlpkMip::_solverName() const { return "GlpkMip"; }
    5.24  
     6.1 --- a/lemon/glpk.h	Thu Feb 26 09:39:02 2009 +0000
     6.2 +++ b/lemon/glpk.h	Thu Feb 26 07:39:16 2009 +0000
     6.3 @@ -119,7 +119,7 @@
     6.4    ///
     6.5    /// This class implements an interface for the GLPK LP solver.
     6.6    ///\ingroup lp_group
     6.7 -  class GlpkLp : public GlpkBase, public LpSolver {
     6.8 +  class GlpkLp : public LpSolver, public GlpkBase {
     6.9    public:
    6.10  
    6.11      ///\e
    6.12 @@ -127,6 +127,11 @@
    6.13      ///\e
    6.14      GlpkLp(const GlpkLp&);
    6.15  
    6.16 +    ///\e
    6.17 +    virtual GlpkLp* cloneSolver() const;
    6.18 +    ///\e
    6.19 +    virtual GlpkLp* newSolver() const;
    6.20 +
    6.21    private:
    6.22  
    6.23      mutable std::vector<double> _primal_ray;
    6.24 @@ -136,9 +141,6 @@
    6.25  
    6.26    protected:
    6.27  
    6.28 -    virtual GlpkLp* _cloneSolver() const;
    6.29 -    virtual GlpkLp* _newSolver() const;
    6.30 -
    6.31      virtual const char* _solverName() const;
    6.32  
    6.33      virtual SolveExitStatus _solve();
    6.34 @@ -203,7 +205,7 @@
    6.35    ///
    6.36    /// This class implements an interface for the GLPK MIP solver.
    6.37    ///\ingroup lp_group
    6.38 -  class GlpkMip : public GlpkBase, public MipSolver {
    6.39 +  class GlpkMip : public MipSolver, public GlpkBase {
    6.40    public:
    6.41  
    6.42      ///\e
    6.43 @@ -211,11 +213,11 @@
    6.44      ///\e
    6.45      GlpkMip(const GlpkMip&);
    6.46  
    6.47 +    virtual GlpkMip* cloneSolver() const;
    6.48 +    virtual GlpkMip* newSolver() const;
    6.49 +
    6.50    protected:
    6.51  
    6.52 -    virtual GlpkMip* _cloneSolver() const;
    6.53 -    virtual GlpkMip* _newSolver() const;
    6.54 -
    6.55      virtual const char* _solverName() const;
    6.56  
    6.57      virtual ColTypes _getColType(int col) const;
     7.1 --- a/lemon/lp_base.h	Thu Feb 26 09:39:02 2009 +0000
     7.2 +++ b/lemon/lp_base.h	Thu Feb 26 07:39:16 2009 +0000
     7.3 @@ -918,8 +918,6 @@
     7.4    protected:
     7.5  
     7.6      //Abstract virtual functions
     7.7 -    virtual LpBase* _newSolver() const = 0;
     7.8 -    virtual LpBase* _cloneSolver() const = 0;
     7.9  
    7.10      virtual int _addColId(int col) { return cols.addIndex(col); }
    7.11      virtual int _addRowId(int row) { return rows.addIndex(row); }
    7.12 @@ -987,11 +985,6 @@
    7.13      /// Virtual destructor
    7.14      virtual ~LpBase() {}
    7.15  
    7.16 -    ///Creates a new LP problem
    7.17 -    LpBase* newSolver() {return _newSolver();}
    7.18 -    ///Makes a copy of the LP problem
    7.19 -    LpBase* cloneSolver() {return _cloneSolver();}
    7.20 -
    7.21      ///Gives back the name of the solver.
    7.22      const char* solverName() const {return _solverName();}
    7.23  
    7.24 @@ -1821,6 +1814,11 @@
    7.25  
    7.26    public:
    7.27  
    7.28 +    ///Allocate a new LP problem instance
    7.29 +    virtual LpSolver* newSolver() const = 0;
    7.30 +    ///Make a copy of the LP problem
    7.31 +    virtual LpSolver* cloneSolver() const = 0;
    7.32 +
    7.33      ///\name Solve the LP
    7.34  
    7.35      ///@{
    7.36 @@ -1935,13 +1933,8 @@
    7.37      Value primal() const { return _getPrimalValue()+obj_const_comp;}
    7.38      ///@}
    7.39  
    7.40 -    LpSolver* newSolver() {return _newSolver();}
    7.41 -    LpSolver* cloneSolver() {return _cloneSolver();}
    7.42 -
    7.43    protected:
    7.44  
    7.45 -    virtual LpSolver* _newSolver() const = 0;
    7.46 -    virtual LpSolver* _cloneSolver() const = 0;
    7.47    };
    7.48  
    7.49  
    7.50 @@ -1975,6 +1968,11 @@
    7.51        UNBOUNDED = 4
    7.52      };
    7.53  
    7.54 +    ///Allocate a new MIP problem instance
    7.55 +    virtual MipSolver* newSolver() const = 0;
    7.56 +    ///Make a copy of the MIP problem
    7.57 +    virtual MipSolver* cloneSolver() const = 0;
    7.58 +
    7.59      ///\name Solve the MIP
    7.60  
    7.61      ///@{
    7.62 @@ -2062,15 +2060,6 @@
    7.63      virtual Value _getSol(int i) const = 0;
    7.64      virtual Value _getSolValue() const = 0;
    7.65  
    7.66 -  public:
    7.67 -
    7.68 -    MipSolver* newSolver() {return _newSolver();}
    7.69 -    MipSolver* cloneSolver() {return _cloneSolver();}
    7.70 -
    7.71 -  protected:
    7.72 -
    7.73 -    virtual MipSolver* _newSolver() const = 0;
    7.74 -    virtual MipSolver* _cloneSolver() const = 0;
    7.75    };
    7.76  
    7.77  
     8.1 --- a/lemon/lp_skeleton.cc	Thu Feb 26 09:39:02 2009 +0000
     8.2 +++ b/lemon/lp_skeleton.cc	Thu Feb 26 07:39:16 2009 +0000
     8.3 @@ -105,10 +105,10 @@
     8.4    LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const
     8.5    { return BASIC; }
     8.6  
     8.7 -  LpSkeleton* LpSkeleton::_newSolver() const
     8.8 +  LpSkeleton* LpSkeleton::newSolver() const
     8.9    { return static_cast<LpSkeleton*>(0); }
    8.10  
    8.11 -  LpSkeleton* LpSkeleton::_cloneSolver() const
    8.12 +  LpSkeleton* LpSkeleton::cloneSolver() const
    8.13    { return static_cast<LpSkeleton*>(0); }
    8.14  
    8.15    const char* LpSkeleton::_solverName() const { return "LpSkeleton"; }
    8.16 @@ -122,10 +122,10 @@
    8.17    MipSkeleton::ProblemType MipSkeleton::_getType() const
    8.18    { return UNDEFINED; }
    8.19  
    8.20 -  MipSkeleton* MipSkeleton::_newSolver() const
    8.21 +  MipSkeleton* MipSkeleton::newSolver() const
    8.22    { return static_cast<MipSkeleton*>(0); }
    8.23  
    8.24 -  MipSkeleton* MipSkeleton::_cloneSolver() const
    8.25 +  MipSkeleton* MipSkeleton::cloneSolver() const
    8.26    { return static_cast<MipSkeleton*>(0); }
    8.27  
    8.28    const char* MipSkeleton::_solverName() const { return "MipSkeleton"; }
     9.1 --- a/lemon/lp_skeleton.h	Thu Feb 26 09:39:02 2009 +0000
     9.2 +++ b/lemon/lp_skeleton.h	Thu Feb 26 07:39:16 2009 +0000
     9.3 @@ -22,10 +22,16 @@
     9.4  #include <lemon/lp_base.h>
     9.5  
     9.6  ///\file
     9.7 -///\brief A skeleton file to implement LP solver interfaces
     9.8 +///\brief Skeleton file to implement LP/MIP solver interfaces
     9.9 +///  
    9.10 +///The classes in this file do nothing, but they can serve as skeletons when
    9.11 +///implementing an interface to new solvers.
    9.12  namespace lemon {
    9.13  
    9.14 -  ///A skeleton class to implement LP solver interfaces
    9.15 +  ///A skeleton class to implement LP/MIP solver base interface
    9.16 +  
    9.17 +  ///This class does nothing, but it can serve as a skeleton when
    9.18 +  ///implementing an interface to new solvers.
    9.19    class SkeletonSolverBase : public virtual LpBase {
    9.20      int col_num,row_num;
    9.21  
    9.22 @@ -136,14 +142,20 @@
    9.23  
    9.24    };
    9.25  
    9.26 -  /// \brief Interface for a skeleton LP solver
    9.27 +  /// \brief Skeleton class for an LP solver interface
    9.28    ///
    9.29 -  /// This class implements an interface for a skeleton LP solver.
    9.30 +  ///This class does nothing, but it can serve as a skeleton when
    9.31 +  ///implementing an interface to new solvers.
    9.32 +
    9.33    ///\ingroup lp_group
    9.34 -  class LpSkeleton : public SkeletonSolverBase, public LpSolver {
    9.35 +  class LpSkeleton : public LpSolver, public SkeletonSolverBase {
    9.36    public:
    9.37 -    LpSkeleton() : SkeletonSolverBase(), LpSolver() {}
    9.38 -
    9.39 +    ///\e
    9.40 +    LpSkeleton() : LpSolver(), SkeletonSolverBase() {}
    9.41 +    ///\e
    9.42 +    virtual LpSkeleton* newSolver() const;
    9.43 +    ///\e
    9.44 +    virtual LpSkeleton* cloneSolver() const;
    9.45    protected:
    9.46  
    9.47      ///\e
    9.48 @@ -173,21 +185,23 @@
    9.49      virtual VarStatus _getRowStatus(int i) const;
    9.50  
    9.51      ///\e
    9.52 -    virtual LpSkeleton* _newSolver() const;
    9.53 -    ///\e
    9.54 -    virtual LpSkeleton* _cloneSolver() const;
    9.55 -    ///\e
    9.56      virtual const char* _solverName() const;
    9.57  
    9.58    };
    9.59  
    9.60 -  /// \brief Interface for a skeleton MIP solver
    9.61 +  /// \brief Skeleton class for a MIP solver interface
    9.62    ///
    9.63 -  /// This class implements an interface for a skeleton MIP solver.
    9.64 +  ///This class does nothing, but it can serve as a skeleton when
    9.65 +  ///implementing an interface to new solvers.
    9.66    ///\ingroup lp_group
    9.67 -  class MipSkeleton : public SkeletonSolverBase, public MipSolver {
    9.68 +  class MipSkeleton : public MipSolver, public SkeletonSolverBase {
    9.69    public:
    9.70 -    MipSkeleton() : SkeletonSolverBase(), MipSolver() {}
    9.71 +    ///\e
    9.72 +    MipSkeleton() : MipSolver(), SkeletonSolverBase() {}
    9.73 +    ///\e
    9.74 +    virtual MipSkeleton* newSolver() const;
    9.75 +    ///\e
    9.76 +    virtual MipSkeleton* cloneSolver() const;
    9.77  
    9.78    protected:
    9.79      ///\e
    9.80 @@ -215,13 +229,7 @@
    9.81      virtual ProblemType _getType() const;
    9.82  
    9.83      ///\e
    9.84 -    virtual MipSkeleton* _newSolver() const;
    9.85 -
    9.86 -    ///\e
    9.87 -    virtual MipSkeleton* _cloneSolver() const;
    9.88 -    ///\e
    9.89      virtual const char* _solverName() const;
    9.90 -
    9.91    };
    9.92  
    9.93  } //namespace lemon
    10.1 --- a/lemon/soplex.cc	Thu Feb 26 09:39:02 2009 +0000
    10.2 +++ b/lemon/soplex.cc	Thu Feb 26 07:39:16 2009 +0000
    10.3 @@ -54,12 +54,12 @@
    10.4      _dual_values.clear();
    10.5    }
    10.6  
    10.7 -  SoplexLp* SoplexLp::_newSolver() const {
    10.8 +  SoplexLp* SoplexLp::newSolver() const {
    10.9      SoplexLp* newlp = new SoplexLp();
   10.10      return newlp;
   10.11    }
   10.12  
   10.13 -  SoplexLp* SoplexLp::_cloneSolver() const {
   10.14 +  SoplexLp* SoplexLp::cloneSolver() const {
   10.15      SoplexLp* newlp = new SoplexLp(*this);
   10.16      return newlp;
   10.17    }
    11.1 --- a/lemon/soplex.h	Thu Feb 26 09:39:02 2009 +0000
    11.2 +++ b/lemon/soplex.h	Thu Feb 26 07:39:16 2009 +0000
    11.3 @@ -73,12 +73,13 @@
    11.4      SoplexLp(const SoplexLp&);
    11.5      /// \e
    11.6      ~SoplexLp();
    11.7 +    /// \e
    11.8 +    virtual SoplexLp* newSolver() const;
    11.9 +    /// \e
   11.10 +    virtual SoplexLp* cloneSolver() const;
   11.11  
   11.12    protected:
   11.13  
   11.14 -    virtual SoplexLp* _newSolver() const;
   11.15 -    virtual SoplexLp* _cloneSolver() const;
   11.16 -
   11.17      virtual const char* _solverName() const;
   11.18  
   11.19      virtual int _addCol();
    12.1 --- a/test/lp_test.cc	Thu Feb 26 09:39:02 2009 +0000
    12.2 +++ b/test/lp_test.cc	Thu Feb 26 07:39:16 2009 +0000
    12.3 @@ -197,6 +197,11 @@
    12.4      buf << "Coeff. of p2 should be 0";
    12.5      check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
    12.6  
    12.7 +    //Test for clone/new
    12.8 +    LP* lpnew = lp.newSolver();
    12.9 +    LP* lpclone = lp.cloneSolver();
   12.10 +    delete lpnew;
   12.11 +    delete lpclone;
   12.12  
   12.13    }
   12.14  
   12.15 @@ -247,7 +252,8 @@
   12.16  
   12.17    if (stat ==  LpSolver::OPTIMAL) {
   12.18      std::ostringstream sbuf;
   12.19 -    sbuf << "Wrong optimal value: the right optimum is " << exp_opt;
   12.20 +    sbuf << "Wrong optimal value (" << lp.primal() <<") with "
   12.21 +         << lp.solverName() <<"\n     the right optimum is " << exp_opt;
   12.22      check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
   12.23    }
   12.24  }
   12.25 @@ -355,6 +361,19 @@
   12.26  
   12.27  }
   12.28  
   12.29 +template<class LP>
   12.30 +void cloneTest()
   12.31 +{
   12.32 +  //Test for clone/new
   12.33 +  
   12.34 +  LP* lp = new LP();
   12.35 +  LP* lpnew = lp->newSolver();
   12.36 +  LP* lpclone = lp->cloneSolver();
   12.37 +  delete lp;
   12.38 +  delete lpnew;
   12.39 +  delete lpclone;
   12.40 +}
   12.41 +
   12.42  int main()
   12.43  {
   12.44    LpSkeleton lp_skel;
   12.45 @@ -365,6 +384,7 @@
   12.46      GlpkLp lp_glpk1,lp_glpk2;
   12.47      lpTest(lp_glpk1);
   12.48      aTest(lp_glpk2);
   12.49 +    cloneTest<GlpkLp>();
   12.50    }
   12.51  #endif
   12.52  
   12.53 @@ -381,6 +401,7 @@
   12.54      std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
   12.55  #endif
   12.56    }
   12.57 +    cloneTest<CplexLp>();
   12.58  #endif
   12.59  
   12.60  #ifdef HAVE_SOPLEX
   12.61 @@ -388,6 +409,7 @@
   12.62      SoplexLp lp_soplex1,lp_soplex2;
   12.63      lpTest(lp_soplex1);
   12.64      aTest(lp_soplex2);
   12.65 +    cloneTest<SoplexLp>();
   12.66    }
   12.67  #endif
   12.68  
   12.69 @@ -396,6 +418,7 @@
   12.70      ClpLp lp_clp1,lp_clp2;
   12.71      lpTest(lp_clp1);
   12.72      aTest(lp_clp2);
   12.73 +    cloneTest<ClpLp>();
   12.74    }
   12.75  #endif
   12.76  
    13.1 --- a/test/mip_test.cc	Thu Feb 26 09:39:02 2009 +0000
    13.2 +++ b/test/mip_test.cc	Thu Feb 26 07:39:16 2009 +0000
    13.3 @@ -106,6 +106,17 @@
    13.4  
    13.5  }
    13.6  
    13.7 +template<class MIP>
    13.8 +void cloneTest()
    13.9 +{
   13.10 +  
   13.11 +  MIP* mip = new MIP();
   13.12 +  MIP* mipnew = mip->newSolver();
   13.13 +  MIP* mipclone = mip->cloneSolver();
   13.14 +  delete mip;
   13.15 +  delete mipnew;
   13.16 +  delete mipclone;
   13.17 +}
   13.18  
   13.19  int main()
   13.20  {
   13.21 @@ -114,6 +125,7 @@
   13.22    {
   13.23      GlpkMip mip1;
   13.24      aTest(mip1);
   13.25 +    cloneTest<GlpkMip>();
   13.26    }
   13.27  #endif
   13.28  
   13.29 @@ -129,6 +141,7 @@
   13.30      std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
   13.31  #endif
   13.32    }
   13.33 +  cloneTest<CplexMip>();
   13.34  #endif
   13.35  
   13.36    return 0;