From 0d7fb8011f5e2176b0aa20b701ab5ccb390b72a4 Mon Sep 17 00:00:00 2001 From: Gennady Pospelov <g.pospelov@fz-juelich.de> Date: Thu, 21 Apr 2016 15:42:02 +0200 Subject: [PATCH] Updates in ROOT minimizers --- .../RootMinimizers/inc/Math/Derivator.h | 4 - .../inc/Math/GSLRandomFunctions.h | 212 ++++++++++ .../RootMinimizers/inc/Math/GSLRndmEngines.h | 24 ++ .../RootMinimizers/inc/Math/RandomFunctions.h | 303 +++++++++++++++ .../RootMinimizers/inc/Math/TRandomEngine.h | 74 ++++ .../inc/Minuit2/BasicMinimumParameters.h | 2 +- .../inc/Minuit2/BasicMinimumState.h | 19 +- .../RootMinimizers/inc/Minuit2/FCNBase.h | 10 +- .../inc/Minuit2/MinimumParameters.h | 9 +- .../RootMinimizers/inc/Minuit2/MinimumState.h | 13 +- .../inc/Minuit2/VariableMetricBuilder.h | 3 +- .../RootMinimizers/src/Math/GSLMultiFit.h | 14 +- .../src/Math/GSLRndmEngines.cxx | 43 ++- .../src/Math/RandomFunctions.cxx | 365 ++++++++++++++++++ .../src/Minuit2/VariableMetricBuilder.cxx | 67 ++-- cmake/modules/SearchInstalledSoftware.cmake | 5 +- dev-tools/code-tools/update_minimizers.py | 2 +- 17 files changed, 1099 insertions(+), 70 deletions(-) create mode 100644 ThirdParty/RootMinimizers/inc/Math/GSLRandomFunctions.h create mode 100644 ThirdParty/RootMinimizers/inc/Math/RandomFunctions.h create mode 100644 ThirdParty/RootMinimizers/inc/Math/TRandomEngine.h create mode 100644 ThirdParty/RootMinimizers/src/Math/RandomFunctions.cxx diff --git a/ThirdParty/RootMinimizers/inc/Math/Derivator.h b/ThirdParty/RootMinimizers/inc/Math/Derivator.h index fffe6882dbf..b56445d3c9f 100644 --- a/ThirdParty/RootMinimizers/inc/Math/Derivator.h +++ b/ThirdParty/RootMinimizers/inc/Math/Derivator.h @@ -33,10 +33,6 @@ #ifndef ROOT_Math_Derivator #define ROOT_Math_Derivator -/** - @defgroup Deriv Numerical Differentiation - @ingroup NumAlgo -*/ #ifndef ROOT_Math_IFunctionfwd #include "Math/IFunctionfwd.h" diff --git a/ThirdParty/RootMinimizers/inc/Math/GSLRandomFunctions.h b/ThirdParty/RootMinimizers/inc/Math/GSLRandomFunctions.h new file mode 100644 index 00000000000..2d7d380493b --- /dev/null +++ b/ThirdParty/RootMinimizers/inc/Math/GSLRandomFunctions.h @@ -0,0 +1,212 @@ +// @(#)root/mathmore:$Id$ +// Authors: L. Moneta 8/2015 + +/********************************************************************** + * * + * Copyright (c) 2015 , ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for random class +// +// +// Created by: Lorenzo Moneta : Tue 4 Aug 2015 +// +// +#ifndef ROOT_Math_GSLRandomFunctions +#define ROOT_Math_GSLRandomFunctions + + +//#include <type_traits> + +#include "Math/RandomFunctions.h" + +#include "Math/GSLRndmEngines.h" + +namespace BA_ROOT { +namespace Math { + + +//___________________________________________________________________________________ + /** + Specialized implementation of the Random functions based on the GSL library. + These will work onlmy with a GSLRandomEngine type + + @ingroup Random + */ + + + template <class EngineType > + class RandomFunctions<EngineType, BA_ROOT::Math::GSLRandomEngine> : public RandomFunctions<EngineType, DefaultEngineType> { + //class RandomFunctions<Engine, ROOT::Math::GSLRandomEngine> { + + //typdef TRandomEngine DefaulEngineType; + + public: + + RandomFunctions() {} + + RandomFunctions(EngineType & rng) : RandomFunctions<EngineType, DefaultEngineType>(rng) {} + + + inline EngineType & Engine() { return RandomFunctions<EngineType,DefaultEngineType>::Rng(); } + + double GausZig(double mean, double sigma) { + return Engine().GaussianZig(sigma) + mean; + } + // double GausRatio(double mean, double sigma) { + // auto & r = RandomFunctions<Engine,DefaultEngineType>::Rng(); + // return r.GaussianRatio(sigma) + mean; + // } + + /** + Gaussian distribution. Default method (use Ziggurat) + */ + double Gaus(double mean = 0, double sigma = 1) { + return mean + Engine().GaussianZig(sigma); + } + + /** + Gaussian distribution (Box-Muller method) + */ + double GausBM(double mean = 0, double sigma = 1) { + return mean + Engine().Gaussian(sigma); + } + + /** + Gaussian distribution (Ratio Method) + */ + double GausR(double mean = 0, double sigma = 1) { + return mean + Engine().GaussianRatio(sigma); + } + + /** + Gaussian Tail distribution + */ + double GaussianTail(double a, double sigma = 1) { + return Engine().GaussianTail(a,sigma); + } + + /** + Bivariate Gaussian distribution with correlation + */ + void Gaussian2D(double sigmaX, double sigmaY, double rho, double &x, double &y) { + Engine().Gaussian2D(sigmaX, sigmaY, rho, x, y); + } + + /** + Exponential distribution + */ + double Exp(double tau) { + return Engine().Exponential(tau); + } + /** + Breit Wigner distribution + */ + double BreitWigner(double mean = 0., double gamma = 1) { + return mean + Engine().Cauchy( gamma/2.0 ); + } + + /** + Landau distribution + */ + double Landau(double mean = 0, double sigma = 1) { + return mean + sigma*Engine().Landau(); + } + + /** + Gamma distribution + */ + double Gamma(double a, double b) { + return Engine().Gamma(a,b); + } + + /** + Log Normal distribution + */ + double LogNormal(double zeta, double sigma) { + return Engine().LogNormal(zeta,sigma); + } + + /** + Chi square distribution + */ + double ChiSquare(double nu) { + return Engine().ChiSquare(nu); + } + + /** + F distrbution + */ + double FDist(double nu1, double nu2) { + return Engine().FDist(nu1,nu2); + } + + /** + t student distribution + */ + double tDist(double nu) { + return Engine().tDist(nu); + } + + /** + generate random numbers in a 2D circle of radious 1 + */ + void Circle(double &x, double &y, double r = 1) { + Engine().Dir2D(x,y); + x *= r; + y *= r; + } + + /** + generate random numbers in a 3D sphere of radious 1 + */ + void Sphere(double &x, double &y, double &z,double r = 1) { + Engine().Dir3D(x,y,z); + x *= r; + y *= r; + z *= r; + } + + /** + Poisson distribution + */ + unsigned int Poisson(double mu) { + return Engine().Poisson(mu); + } + + /** + Binomial distribution + */ + unsigned int Binomial(unsigned int ntot, double prob) { + return Engine().Binomial(prob,ntot); + } + + /** + Negative Binomial distribution + First parameter is n, second is probability + To be consistent with Random::Binomial + */ + unsigned int NegativeBinomial(double n, double prob) { + return Engine().NegativeBinomial(prob,n); + } + + /** + Multinomial distribution + */ + std::vector<unsigned int> Multinomial( unsigned int ntot, const std::vector<double> & p ) { + return Engine().Multinomial(ntot,p); + } + + + + }; + + + + +} // namespace Math +} // namespace ROOT + +#endif /* ROOT_Math_GSLRandomFunctions */ diff --git a/ThirdParty/RootMinimizers/inc/Math/GSLRndmEngines.h b/ThirdParty/RootMinimizers/inc/Math/GSLRndmEngines.h index 20df9962bea..0772437fbd8 100644 --- a/ThirdParty/RootMinimizers/inc/Math/GSLRndmEngines.h +++ b/ThirdParty/RootMinimizers/inc/Math/GSLRndmEngines.h @@ -34,6 +34,7 @@ #include <string> #include <vector> + namespace BA_ROOT { namespace Math { @@ -108,6 +109,12 @@ namespace Math { 0 is excluded and 1 is included */ double operator() () const; + + /** + Generate a random number between ]0,1] + 0 is excluded and 1 is included + */ + double Rndm() const { return (*this)(); } /** Generate an integer number between [0,max-1] (including 0 and max-1) @@ -279,6 +286,7 @@ namespace Math { */ class GSLRngMT : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngMT(); }; @@ -292,6 +300,7 @@ namespace Math { */ class GSLRngRanLux : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanLux(); }; @@ -305,6 +314,7 @@ namespace Math { */ class GSLRngRanLuxS1 : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanLuxS1(); }; typedef GSLRngRanLuxS1 GSLRngRanLux1; // for backward compatibility @@ -319,6 +329,7 @@ namespace Math { */ class GSLRngRanLuxS2 : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanLuxS2(); }; typedef GSLRngRanLuxS2 GSLRngRanLux2; // for backward compatibility @@ -333,6 +344,7 @@ namespace Math { */ class GSLRngRanLuxD1 : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanLuxD1(); }; @@ -346,6 +358,7 @@ namespace Math { */ class GSLRngRanLuxD2 : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanLuxD2(); }; typedef GSLRngRanLuxD2 GSLRngRanLux48; // for backward compatibility @@ -360,6 +373,7 @@ namespace Math { */ class GSLRngTaus : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngTaus(); }; @@ -372,6 +386,7 @@ namespace Math { */ class GSLRngGFSR4 : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngGFSR4(); }; @@ -384,6 +399,7 @@ namespace Math { */ class GSLRngCMRG : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngCMRG(); }; @@ -396,6 +412,7 @@ namespace Math { */ class GSLRngMRG : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngMRG(); }; @@ -409,6 +426,7 @@ namespace Math { */ class GSLRngRand : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRand(); }; @@ -421,6 +439,7 @@ namespace Math { */ class GSLRngRanMar : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngRanMar(); }; @@ -433,6 +452,7 @@ namespace Math { */ class GSLRngMinStd : public GSLRandomEngine { public: + typedef GSLRandomEngine BaseType; GSLRngMinStd(); }; @@ -442,6 +462,10 @@ namespace Math { } // namespace Math } // namespace ROOT +// random functions specialization for GSL +// needs to be defined after defining GSLRandomEngine class + +#include "Math/GSLRandomFunctions.h" #endif /* ROOT_Math_GSLRndmEngines */ diff --git a/ThirdParty/RootMinimizers/inc/Math/RandomFunctions.h b/ThirdParty/RootMinimizers/inc/Math/RandomFunctions.h new file mode 100644 index 00000000000..3348b7a9425 --- /dev/null +++ b/ThirdParty/RootMinimizers/inc/Math/RandomFunctions.h @@ -0,0 +1,303 @@ +// @(#)root/mathcore:$Id$ +// Authors: L. Moneta 8/2015 + +/********************************************************************** + * * + * Copyright (c) 2015 , ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// Header file for random class +// +// +// Created by: Lorenzo Moneta : Tue 4 Aug 2015 +// +// +#ifndef ROOT_Math_RandomFunctions +#define ROOT_Math_RandomFunctions + + +#include <type_traits> +#include <cmath> +//#include "Rtypes.h" +//#include "TMath.h" +#include "TMVA/Types.h" +#include <cassert> +#include <vector> + +#include "TRandomEngine.h" + + +namespace BA_ROOT { +namespace Math { + + +//___________________________________________________________________________________ + + + // class DefaultEngineType {}; + + + /** + Documentation for the RandomFunction class + + @ingroup Random + */ + + + typedef TRandomEngine DefaultEngineType; + //class DefaultEngineType {}; // for generic types + + + + /** + Definition of the generic impelmentation class for the RandomFunctions. + Needs to have specialized implementations on the different type of engines + */ + template <class EngineBaseType> + class RandomFunctionsImpl { + public: + void SetEngine(void *) {} + }; + + /** + Implementation class for the RandomFunction for all the engined that derives from + TRandomEngine class, which defines an interface which has TRandomEngine::Rndm() + In this way we can have a common implementation for the RandomFunctions + */ + + template<> + class RandomFunctionsImpl<TRandomEngine> { + + public: + + /// class constructor + RandomFunctionsImpl() {} + + void SetEngine(void *r) { + fBaseEngine = static_cast<TRandomEngine*>(r); + assert(fBaseEngine); // to be sure the static cast works + } + + + ///Generate binomial numbers + int Binomial(int ntot, double prob); + + /// Return a number distributed following a BreitWigner function with mean and gamma. + double BreitWigner(double mean, double gamma); + + /// Generates random vectors, uniformly distributed over a circle of given radius. + /// Input : r = circle radius + /// Output: x,y a random 2-d vector of length r + void Circle(double &x, double &y, double r); + + /// Returns an exponential deviate. + /// exp( -t/tau ) + double Exp(double tau); + + /// generate Gaussian number using Box-Muller method + double GausBM( double mean, double sigma); + + /// generate random numbers according to the Accemptance-Complemet-Ratio method + double GausACR( double mean, double sigma); + + /// Generate a random number following a Landau distribution + /// with location parameter mu and scale parameter sigma: + /// Landau( (x-mu)/sigma ) +// double Landau(double mu, double sigma); + + /// Generates a random integer N according to a Poisson law. + /// Prob(N) = exp(-mean)*mean^N/Factorial(N) +// int Poisson(double mean); +// double PoissonD(double mean); + + /// Generate numbers distributed following a gaussian with mean=0 and sigma=1. + /// Using the Box-Muller method + void Rannor(double &a, double &b); + + /// Generates random vectors, uniformly distributed over the surface + /// of a sphere of given radius. + void Sphere(double &x, double &y, double &z, double r); + + /// generate random numbers following a Uniform distribution in the [a,b] interval + double Uniform(double a, double b); + double Uniform(double a); + + protected: + TRandomEngine * fBaseEngine; + + private: + // Internal method used by the functions + double Rndm() { return fBaseEngine->Rndm(); } + // for internal usage + double Gaus(double mean, double sigma) { return GausACR(mean,sigma); } + + + }; + + + template < class Engine, class EngineBaseType> + class RandomFunctions { //: public RandomFunctionsImpl<EngineBaseType> { + + + public: + + //RandomFunctions() {} + + RandomFunctions(Engine & rng) : fEngine(&rng) { + fImpl.SetEngine(&rng); + } + + /// destructor (no op) we do not mantain the engine) + ~RandomFunctions() {} + + + /// non-virtual method + inline double operator() () { return (*fEngine)(); } + + + ///Generate binomial numbers + int Binomial(int ntot, double prob) { + return fImpl.Binomial(ntot,prob); + } + + /// Return a number distributed following a BreitWigner function with mean and gamma. + double BreitWigner(double mean, double gamma) { + return fImpl.BreitWigner(mean,gamma); + } + + /// Generates random vectors, uniformly distributed over a circle of given radius. + /// Input : r = circle radius + /// Output: x,y a random 2-d vector of length r + void Circle(double &x, double &y, double r) { + return fImpl.Circle(x,y,r); + } + + /// Returns an exponential deviate. + /// exp( -t/tau ) + double Exp(double tau) { + return fImpl.Exp(tau); + } + + /// generate Gaussian number using Box-Muller method + double GausBM( double mean, double sigma) { + return fImpl.GausBM(mean,sigma); + } + + /// generate random numbers according to the Accemptance-Complemet-Ratio method + double GausACR( double mean, double sigma) { + return fImpl.GausACR(mean, sigma); + } + + /// Generate a random number following a Landau distribution + /// with location parameter mu and scale parameter sigma: + /// Landau( (x-mu)/sigma ) + double Landau(double mu, double sigma) { + return fImpl.Landau(mu,sigma); + } + + /// Generates a random integer N according to a Poisson law. + /// Prob(N) = exp(-mean)*mean^N/Factorial(N) + int Poisson(double mean) { return fImpl.Poisson(mean); } + double PoissonD(double mean) { return fImpl.PoissonD(mean); } + + /// Generate numbers distributed following a gaussian with mean=0 and sigma=1. + /// Using the Box-Muller method + void Rannor(double &a, double &b) { + return fImpl.Rannor(a,b); + } + + /// Generates random vectors, uniformly distributed over the surface + /// of a sphere of given radius. + void Sphere(double &x, double &y, double &z, double r) { + return fImpl.Sphere(x,y,z,r); + } + + /// generate random numbers following a Uniform distribution in the [a,b] interval + double Uniform(double a, double b) { + return (b-a) * Rndm_impl() + a; + } + + /// generate random numbers following a Uniform distribution in the [0,a] interval + double Uniform(double a) { + return a * Rndm_impl() ; + } + + + /// generate Gaussian number using defqault method + inline double Gaus( double mean, double sigma) { + return fImpl.GausACR(mean,sigma); + } + + + // /// re-implement Gaussian + // double GausBM2(double mean, double sigma) { + // double y = Rndm_impl(); + // double z = Rndm_impl(); + // double x = z * 6.28318530717958623; + // double radius = std::sqrt(-2*std::log(y)); + // double g = radius * std::sin(x); + // return mean + g * sigma; + // } + + + /// methods which are only for GSL random generators + + + /// Gamma functions (not implemented here, requires a GSL random engine) + double Gamma( double , double ) { + //r.Error("Error: Gamma() requires a GSL Engine type"); + static_assert(std::is_fundamental<Engine>::value,"Error: Gamma() requires a GSL Engine type"); + return 0; + } + double LogNormal(double, double) { + static_assert(std::is_fundamental<Engine>::value,"Error: LogNormal() requires a GSL Engine type"); + return 0; + } + double ChiSquare(double) { + static_assert(std::is_fundamental<Engine>::value,"Error: ChiSquare() requires a GSL Engine type"); + return 0; + } + double FDist(double, double) { + static_assert(std::is_fundamental<Engine>::value,"Error: FDist() requires a GSL Engine type"); + return 0; + } + double tDist(double) { + static_assert(std::is_fundamental<Engine>::value,"Error: tDist() requires a GSL Engine type"); + return 0; + } + unsigned int NegativeBinomial(double , double ) { + static_assert(std::is_fundamental<Engine>::value,"Error: NegativeBinomial() requires a GSL Engine type"); + return 0; + } + std::vector<unsigned int> MultiNomial(unsigned int, const std::vector<double> &){ + static_assert(std::is_fundamental<Engine>::value,"Error: MultiNomial() requires a GSL Engine type"); + return std::vector<unsigned int>(); + } + + + protected: + + Engine & Rng() { assert(fEngine); return *fEngine; } + + /// Internal impelmentation to return random number + /// Since this one is not a virtual function is faster than Rndm + inline double Rndm_impl() { return (*fEngine)(); } + + + private: + + Engine * fEngine; //! random number generator engine + RandomFunctionsImpl<EngineBaseType> fImpl; //! instance of the class implementing the functions + + + }; + + + + +} // namespace Math +} // namespace ROOT + +#endif /* ROOT_Math_RandomFunctions */ diff --git a/ThirdParty/RootMinimizers/inc/Math/TRandomEngine.h b/ThirdParty/RootMinimizers/inc/Math/TRandomEngine.h new file mode 100644 index 00000000000..8c037d33495 --- /dev/null +++ b/ThirdParty/RootMinimizers/inc/Math/TRandomEngine.h @@ -0,0 +1,74 @@ +// @(#)root/mathcore:$Id$ +// Author: L. Moneta Tue Aug 4 2015 + +/********************************************************************** + * * + * Copyright (c) 2015 LCG ROOT Math Team, CERN/PH-SFT * + * * + * * + **********************************************************************/ + +// random engines based on ROOT + +#ifndef ROOT_Math_TRandomEngine +#define ROOT_Math_TRandomEngine + + + +namespace BA_ROOT { + + namespace Math { + + class RandomBaseEngine { + public: + virtual double Rndm() = 0; + virtual ~RandomBaseEngine() {} + }; + + + class TRandomEngine : public RandomBaseEngine { + public: + virtual ~TRandomEngine() {} + }; + + class LCGEngine : public TRandomEngine { + + + public: + + typedef TRandomEngine BaseType; + + LCGEngine() : fSeed(65539) { } + + virtual ~LCGEngine() {} + + void SetSeed(unsigned int seed) { fSeed = seed; } + + virtual double Rndm() { + //double Rndm() { + return Rndm_impl(); + } + double Rndm_impl() { + const double kCONS = 4.6566128730774E-10; // (1/pow(2,31) + unsigned int rndm = IntRndm(); // generate integer number + if (rndm != 0) return kCONS*rndm; + return Rndm_impl(); + } + inline double operator() () { return Rndm_impl(); } + + unsigned int IntRndm() { + fSeed = (1103515245 * fSeed + 12345) & 0x7fffffffUL; + return fSeed; + } + + private: + unsigned int fSeed; + }; + + + } // end namespace Math + +} // end namespace ROOT + + +#endif /* ROOT_Math_TRandomEngine */ diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumParameters.h b/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumParameters.h index 150c11ee768..b9629f272e2 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumParameters.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumParameters.h @@ -25,7 +25,7 @@ class BasicMinimumParameters { public: - BasicMinimumParameters(unsigned int n) : fParameters(MnAlgebraicVector(n)), fStepSize(MnAlgebraicVector(n)), fFVal(0.), fValid(false), fHasStep(false) {} + BasicMinimumParameters(unsigned int n, double fval) : fParameters(MnAlgebraicVector(n)), fStepSize(MnAlgebraicVector(n)), fFVal(fval), fValid(false), fHasStep(false) {} BasicMinimumParameters(const MnAlgebraicVector& avec, double fval) : fParameters(avec), fStepSize(avec.size()), fFVal(fval), fValid(true), fHasStep(false) {} diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumState.h b/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumState.h index 57f042e7e4c..00a285be220 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumState.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/BasicMinimumState.h @@ -27,19 +27,23 @@ class BasicMinimumState { public: - BasicMinimumState(unsigned int n) : - fParameters(MinimumParameters(n)), fError(MinimumError(n)), - fGradient(FunctionGradient(n)), fEDM(0.), fNFcn(0) {} + // constructor without parameter values but with function value, edm and nfcn + BasicMinimumState(unsigned int n, double fval, double edm, int nfcn) : + fParameters(MinimumParameters(n,fval)), fError(MinimumError(n)), + fGradient(FunctionGradient(n)), fEDM(edm), fNFcn(nfcn) {} + BasicMinimumState(const MinimumParameters& states, const MinimumError& err, - const FunctionGradient& grad, double edm, int nfcn) : - fParameters(states), fError(err), fGradient(grad), fEDM(edm), fNFcn(nfcn) {} + const FunctionGradient& grad, double edm, int nfcn) : + fParameters(states), fError(err), fGradient(grad), fEDM(edm), fNFcn(nfcn) {} - BasicMinimumState(const MinimumParameters& states, double edm, int nfcn) : fParameters(states), fError(MinimumError(states.Vec().size())), fGradient(FunctionGradient(states.Vec().size())), fEDM(edm), fNFcn(nfcn) {} + BasicMinimumState(const MinimumParameters& states, double edm, int nfcn) : fParameters(states), fError(MinimumError(states.Vec().size())), + fGradient(FunctionGradient(states.Vec().size())), fEDM(edm), fNFcn(nfcn) + {} ~BasicMinimumState() {} BasicMinimumState(const BasicMinimumState& state) : - fParameters(state.fParameters), fError(state.fError), fGradient(state.fGradient), fEDM(state.fEDM), fNFcn(state.fNFcn) {} + fParameters(state.fParameters), fError(state.fError), fGradient(state.fGradient), fEDM(state.fEDM), fNFcn(state.fNFcn) {} BasicMinimumState& operator=(const BasicMinimumState& state) { fParameters = state.fParameters; @@ -68,6 +72,7 @@ public: double Edm() const {return fEDM;} int NFcn() const {return fNFcn;} + bool IsValid() const { if(HasParameters() && HasCovariance()) return Parameters().IsValid() && Error().IsValid(); diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/FCNBase.h b/ThirdParty/RootMinimizers/inc/Minuit2/FCNBase.h index 61095159f3e..c31c9445b35 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/FCNBase.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/FCNBase.h @@ -23,10 +23,12 @@ namespace BA_ROOT { /** -@defgroup Minuit Minuit2 Minimization Library + \defgroup Minuit Minuit2 Minimization Library - Object-oriented implementation of the MINUIT minimization package. - More information is available at the home page of the \ref Minuit2 package. + New Object-oriented implementation of the MINUIT minimization package. + More information is available at the home page of the \ref Minuit2Page "Minuit2" minimization package". + + \ingroup Math */ @@ -38,7 +40,7 @@ Interface (abstract class) defining the function to be minimized, which has to b @author Fred James and Matthias Winkler; modified by Andras Zsenei and Lorenzo Moneta -@ingroup Minuit +\ingroup Minuit */ diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/MinimumParameters.h b/ThirdParty/RootMinimizers/inc/Minuit2/MinimumParameters.h index db500424212..b6688fd9bec 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/MinimumParameters.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/MinimumParameters.h @@ -22,15 +22,16 @@ class MinimumParameters { public: - MinimumParameters(unsigned int n) : - fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(n))) {} + MinimumParameters(unsigned int n, double fval = 0) : + fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(n,fval))) {} /** takes the Parameter vector */ MinimumParameters(const MnAlgebraicVector& avec, double fval) : - fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(avec, fval))) {} + fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(avec, fval))) {} /** takes the Parameter vector plus step size x1 - x0 = dirin */ - MinimumParameters(const MnAlgebraicVector& avec, const MnAlgebraicVector& dirin, double fval) : fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(avec, dirin, fval))) {} + MinimumParameters(const MnAlgebraicVector& avec, const MnAlgebraicVector& dirin, double fval) : + fData(MnRefCountedPointer<BasicMinimumParameters>(new BasicMinimumParameters(avec, dirin, fval))) {} ~MinimumParameters() {} diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/MinimumState.h b/ThirdParty/RootMinimizers/inc/Minuit2/MinimumState.h index bce046d2a75..8168dc34d53 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/MinimumState.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/MinimumState.h @@ -31,17 +31,20 @@ class MinimumState { public: /** invalid state */ - MinimumState(unsigned int n) : - fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(n))) {} + MinimumState(unsigned int n) : + fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(n,0.,0.,0.))) {} + /** state without parameters and errors (only function value an, edm and nfcn) */ + MinimumState(double fval, double edm, int nfcn) : + fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(0, fval, edm, nfcn))) {} /** state with parameters only (from stepping methods like Simplex, Scan) */ - MinimumState(const MinimumParameters& states, double edm, int nfcn) : - fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(states, edm, nfcn))) {} + MinimumState(const MinimumParameters& states, double edm, int nfcn) : + fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(states, edm, nfcn))) {} /** state with parameters, Gradient and covariance (from Gradient methods such as Migrad) */ MinimumState(const MinimumParameters& states, const MinimumError& err, const FunctionGradient& grad, double edm, int nfcn) : - fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(states, err, grad, edm, nfcn))) {} + fData(MnRefCountedPointer<BasicMinimumState>(new BasicMinimumState(states, err, grad, edm, nfcn))) {} ~MinimumState() {} diff --git a/ThirdParty/RootMinimizers/inc/Minuit2/VariableMetricBuilder.h b/ThirdParty/RootMinimizers/inc/Minuit2/VariableMetricBuilder.h index 5eb6c9afb12..89fa28aca30 100644 --- a/ThirdParty/RootMinimizers/inc/Minuit2/VariableMetricBuilder.h +++ b/ThirdParty/RootMinimizers/inc/Minuit2/VariableMetricBuilder.h @@ -23,6 +23,7 @@ namespace BA_ROOT { /** Build (find) function minimum using the Variable Metric method (MIGRAD) + */ class VariableMetricBuilder : public MinimumBuilder { @@ -41,7 +42,7 @@ public: const VariableMetricEDMEstimator& Estimator() const {return fEstimator;} const DavidonErrorUpdator& ErrorUpdator() const {return fErrorUpdator;} - void AddResult(std::vector<MinimumState>& result, const MinimumState & state, bool store = false) const; + void AddResult(std::vector<MinimumState>& result, const MinimumState & state) const; private: diff --git a/ThirdParty/RootMinimizers/src/Math/GSLMultiFit.h b/ThirdParty/RootMinimizers/src/Math/GSLMultiFit.h index 232a3c08834..c8194409566 100644 --- a/ThirdParty/RootMinimizers/src/Math/GSLMultiFit.h +++ b/ThirdParty/RootMinimizers/src/Math/GSLMultiFit.h @@ -31,6 +31,7 @@ #include "gsl/gsl_matrix.h" #include "gsl/gsl_multifit_nlin.h" #include "gsl/gsl_blas.h" +#include "gsl/gsl_version.h" #include "GSLMultiFitFunctionWrapper.h" #include "Math/IFunction.h" @@ -143,10 +144,8 @@ public: /// gradient value at the minimum const double * Gradient() const { if (fSolver == 0) return 0; -#ifdef BORNAGAIN_GSL_BIGGEROREQUAL_2 - gsl_matrix * J = gsl_matrix_alloc(fSolver->fdf->n, fSolver->fdf->p); - gsl_multifit_fdfsolver_jac(fSolver, J); - gsl_multifit_gradient(J, fSolver->f,fVec); +#if GSL_MAJOR_VERSION > 1 + fType->gradient(fSolver->state, fVec); #else gsl_multifit_gradient(fSolver->J, fSolver->f,fVec); #endif @@ -160,10 +159,11 @@ public: unsigned int npar = fSolver->fdf->p; fCov = gsl_matrix_alloc( npar, npar ); static double kEpsrel = 0.0001; -#ifdef BORNAGAIN_GSL_BIGGEROREQUAL_2 - gsl_matrix * J = gsl_matrix_alloc(fSolver->fdf->n, fSolver->fdf->p); - gsl_multifit_fdfsolver_jac(fSolver, J); +#if GSL_MAJOR_VERSION > 1 + gsl_matrix* J = gsl_matrix_alloc(npar,npar); + gsl_multifit_fdfsolver_jac (fSolver, J); int ret = gsl_multifit_covar(J, kEpsrel, fCov); + gsl_matrix_free(J); #else int ret = gsl_multifit_covar(fSolver->J, kEpsrel, fCov); #endif diff --git a/ThirdParty/RootMinimizers/src/Math/GSLRndmEngines.cxx b/ThirdParty/RootMinimizers/src/Math/GSLRndmEngines.cxx index 85165c3c5c7..f5214b3b54b 100644 --- a/ThirdParty/RootMinimizers/src/Math/GSLRndmEngines.cxx +++ b/ThirdParty/RootMinimizers/src/Math/GSLRndmEngines.cxx @@ -159,14 +159,16 @@ namespace Math { } std::string GSLRandomEngine::Name() const { - //---------------------------------------------------- + ////////////////////////////////////////////////////////////////////////// + assert ( fRng != 0); assert ( fRng->Rng() != 0 ); return std::string( gsl_rng_name( fRng->Rng() ) ); } unsigned int GSLRandomEngine::Size() const { - //---------------------------------------------------- + ////////////////////////////////////////////////////////////////////////// + assert (fRng != 0); return gsl_rng_size( fRng->Rng() ); } @@ -300,10 +302,12 @@ namespace Math { // generators //---------------------------------------------------- - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngMT::GSLRngMT() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_mt19937)); + Initialize(); } @@ -311,73 +315,92 @@ namespace Math { GSLRngRanLux::GSLRngRanLux() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranlux) ); + Initialize(); } // second generation of Ranlux (single precision version - luxury 1) GSLRngRanLuxS1::GSLRngRanLuxS1() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranlxs1) ); + Initialize(); } // second generation of Ranlux (single precision version - luxury 2) GSLRngRanLuxS2::GSLRngRanLuxS2() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranlxs2) ); + Initialize(); } // double precision version - luxury 1 GSLRngRanLuxD1::GSLRngRanLuxD1() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranlxd1) ); + Initialize(); } // double precision version - luxury 2 GSLRngRanLuxD2::GSLRngRanLuxD2() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranlxd2) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngTaus::GSLRngTaus() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_taus2) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngGFSR4::GSLRngGFSR4() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_gfsr4) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngCMRG::GSLRngCMRG() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_cmrg) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngMRG::GSLRngMRG() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_mrg) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngRand::GSLRngRand() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_rand) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngRanMar::GSLRngRanMar() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_ranmar) ); + Initialize(); } - //---------------------------------------------------- + ///////////////////////////////////////////////////////////////////////////// + GSLRngMinStd::GSLRngMinStd() : GSLRandomEngine() { SetType(new GSLRngWrapper(gsl_rng_minstd) ); + Initialize(); } diff --git a/ThirdParty/RootMinimizers/src/Math/RandomFunctions.cxx b/ThirdParty/RootMinimizers/src/Math/RandomFunctions.cxx new file mode 100644 index 00000000000..bebca8cd5d3 --- /dev/null +++ b/ThirdParty/RootMinimizers/src/Math/RandomFunctions.cxx @@ -0,0 +1,365 @@ +// @(#)root/mathcore:$Id$ +// Authors: L. Moneta 8/2015 + +/********************************************************************** + * * + * Copyright (c) 2015 , ROOT MathLib Team * + * * + * * + **********************************************************************/ + +// file for random class +// +// +// Created by: Lorenzo Moneta : Tue 4 Aug 2015 +// +// +#include "Math/RandomFunctions.h" + +//#include "Math/DistFunc.h" + +//#include "TMath.h" + +namespace BA_ROOT { +namespace Math { + + +Int_t RandomFunctionsImpl<TRandomEngine>::Binomial(Int_t ntot, Double_t prob) +{ + if (prob < 0 || prob > 1) return 0; + Int_t n = 0; + for (Int_t i=0;i<ntot;i++) { + if (Rndm() > prob) continue; + n++; + } + return n; +} + + //////////////////////////////////////////////////////////////////////////////// +/// Return a number distributed following a BreitWigner function with mean and gamma. + +Double_t RandomFunctionsImpl<TRandomEngine>::BreitWigner(Double_t mean, Double_t gamma) +{ + Double_t rval, displ; + rval = 2*Rndm() - 1; + displ = 0.5*gamma*std::tan(rval*M_PI/2.); + + return (mean+displ); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Generates random vectors, uniformly distributed over a circle of given radius. +/// Input : r = circle radius +/// Output: x,y a random 2-d vector of length r + +void RandomFunctionsImpl<TRandomEngine>::Circle(Double_t &x, Double_t &y, Double_t r) +{ + Double_t phi = Uniform(0,M_PI*2.0); + x = r*std::cos(phi); + y = r*std::sin(phi); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns an exponential deviate. +/// +/// exp( -t/tau ) + +Double_t RandomFunctionsImpl<TRandomEngine>::Exp(Double_t tau) +{ + Double_t x = Rndm(); // uniform on ] 0, 1 ] + Double_t t = -tau * std::log( x ); // convert to exponential distribution + return t; +} + + + + +double RandomFunctionsImpl<TRandomEngine>::GausBM(double mean, double sigma) { + double y = Rndm(); + double z = Rndm(); + double x = z * 6.28318530717958623; + double radius = std::sqrt(-2*std::log(y)); + double g = radius * std::sin(x); + return mean + g * sigma; +} + + + // double GausImpl(TRandomEngine * r, double mean, double sigma) { + // double y = r->Rndm(); + // double z = r->Rndm(); + // double x = z * 6.28318530717958623; + // double radius = std::sqrt(-2*std::log(y)); + // double g = radius * std::sin(x); + // return mean + g * sigma; + // } + +double RandomFunctionsImpl<TRandomEngine>::GausACR(Double_t mean, Double_t sigma) +{ + const Double_t kC1 = 1.448242853; + const Double_t kC2 = 3.307147487; + const Double_t kC3 = 1.46754004; + const Double_t kD1 = 1.036467755; + const Double_t kD2 = 5.295844968; + const Double_t kD3 = 3.631288474; + const Double_t kHm = 0.483941449; + const Double_t kZm = 0.107981933; + const Double_t kHp = 4.132731354; + const Double_t kZp = 18.52161694; + const Double_t kPhln = 0.4515827053; + const Double_t kHm1 = 0.516058551; + const Double_t kHp1 = 3.132731354; + const Double_t kHzm = 0.375959516; + const Double_t kHzmp = 0.591923442; + /*zhm 0.967882898*/ + + const Double_t kAs = 0.8853395638; + const Double_t kBs = 0.2452635696; + const Double_t kCs = 0.2770276848; + const Double_t kB = 0.5029324303; + const Double_t kX0 = 0.4571828819; + const Double_t kYm = 0.187308492 ; + const Double_t kS = 0.7270572718 ; + const Double_t kT = 0.03895759111; + + Double_t result; + Double_t rn,x,y,z; + + do { + y = Rndm(); + + if (y>kHm1) { + result = kHp*y-kHp1; break; } + + else if (y<kZm) { + rn = kZp*y-1; + result = (rn>0) ? (1+rn) : (-1+rn); + break; + } + + else if (y<kHm) { + rn = Rndm(); + rn = rn-1+rn; + z = (rn>0) ? 2-rn : -2-rn; + if ((kC1-y)*(kC3+std::abs(z))<kC2) { + result = z; break; } + else { + x = rn*rn; + if ((y+kD1)*(kD3+x)<kD2) { + result = rn; break; } + else if (kHzmp-y<exp(-(z*z+kPhln)/2)) { + result = z; break; } + else if (y+kHzm<exp(-(x+kPhln)/2)) { + result = rn; break; } + } + } + + while (1) { + x = Rndm(); + y = kYm * Rndm(); + z = kX0 - kS*x - y; + if (z>0) + rn = 2+y/x; + else { + x = 1-x; + y = kYm-y; + rn = -(2+y/x); + } + if ((y-kAs+x)*(kCs+x)+kBs<0) { + result = rn; break; } + else if (y<x+kT) + if (rn*rn<4*(kB-log(x))) { + result = rn; break; } + } + } while(0); + + return mean + sigma * result; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Generate a random number following a Landau distribution +/// with location parameter mu and scale parameter sigma: +/// Landau( (x-mu)/sigma ) +/// Note that mu is not the mpv(most probable value) of the Landa distribution +/// and sigma is not the standard deviation of the distribution which is not defined. +/// For mu =0 and sigma=1, the mpv = -0.22278 +/// +/// The Landau random number generation is implemented using the +/// function landau_quantile(x,sigma), which provides +/// the inverse of the landau cumulative distribution. +/// landau_quantile has been converted from CERNLIB ranlan(G110). + +//Double_t RandomFunctionsImpl<TRandomEngine>::Landau(Double_t mu, Double_t sigma) +//{ +// if (sigma <= 0) return 0; +// Double_t x = Rndm(); +// Double_t res = mu + BA_ROOT::Math::landau_quantile(x, sigma); +// return res; +//} + +//////////////////////////////////////////////////////////////////////////////// +/// Generates a random integer N according to a Poisson law. +/// Prob(N) = exp(-mean)*mean^N/Factorial(N) +/// +/// Use a different procedure according to the mean value. +/// The algorithm is the same used by CLHEP. +/// For lower value (mean < 25) use the rejection method based on +/// the exponential. +/// For higher values use a rejection method comparing with a Lorentzian +/// distribution, as suggested by several authors. +/// This routine since is returning 32 bits integer will not work for values +/// larger than 2*10**9. +/// One should then use the Trandom::PoissonD for such large values. + +//Int_t RandomFunctionsImpl<TRandomEngine>::Poisson(Double_t mean) +//{ +// Int_t n; +// if (mean <= 0) return 0; +// if (mean < 25) { +// Double_t expmean = std::exp(-mean); +// Double_t pir = 1; +// n = -1; +// while(1) { +// n++; +// pir *= Rndm(); +// if (pir <= expmean) break; +// } +// return n; +// } +// // for large value we use inversion method +// else if (mean < 1E9) { +// Double_t em, t, y; +// Double_t sq, alxm, g; +// Double_t pi = M_PI; + +// sq = std::sqrt(2.0*mean); +// alxm = std::log(mean); +// g = mean*alxm - TMath::LnGamma(mean + 1.0); + +// do { +// do { +// y = std::tan(pi*Rndm()); +// em = sq*y + mean; +// } while( em < 0.0 ); + +// em = std::floor(em); +// t = 0.9*(1.0 + y*y)* std::exp(em*alxm - TMath::LnGamma(em + 1.0) - g); +// } while( Rndm() > t ); + +// return static_cast<Int_t> (em); + +// } +// else { +// // use Gaussian approximation vor very large values +// n = Int_t(Gaus(0,1)*std::sqrt(mean) + mean +0.5); +// return n; +// } +//} + +////////////////////////////////////////////////////////////////////////////////// +///// Generates a random number according to a Poisson law. +///// Prob(N) = exp(-mean)*mean^N/Factorial(N) +///// +///// This function is a variant of RandomFunctionsImpl<TRandomEngine>::Poisson returning a double +///// instead of an integer. + +//Double_t RandomFunctionsImpl<TRandomEngine>::PoissonD(Double_t mean) +//{ +// Int_t n; +// if (mean <= 0) return 0; +// if (mean < 25) { +// Double_t expmean = std::exp(-mean); +// Double_t pir = 1; +// n = -1; +// while(1) { +// n++; +// pir *= Rndm(); +// if (pir <= expmean) break; +// } +// return static_cast<Double_t>(n); +// } +// // for large value we use inversion method +// else if (mean < 1E9) { +// Double_t em, t, y; +// Double_t sq, alxm, g; +// Double_t pi = M_PI; + +// sq = std::sqrt(2.0*mean); +// alxm = std::log(mean); +// g = mean*alxm - TMath::LnGamma(mean + 1.0); + +// do { +// do { +// y = std::tan(pi*Rndm()); +// em = sq*y + mean; +// } while( em < 0.0 ); + +// em = std::floor(em); +// t = 0.9*(1.0 + y*y)* std::exp(em*alxm - TMath::LnGamma(em + 1.0) - g); +// } while( Rndm() > t ); + +// return em; + +// } else { +// // use Gaussian approximation vor very large values +// return Gaus(0,1)*std::sqrt(mean) + mean +0.5; +// } +//} + + +//////////////////////////////////////////////////////////////////////////////// +/// Return 2 numbers distributed following a gaussian with mean=0 and sigma=1. + +void RandomFunctionsImpl<TRandomEngine>::Rannor(Double_t &a, Double_t &b) +{ + Double_t r, x, y, z; + + y = Rndm(); + z = Rndm(); + x = z * 6.28318530717958623; + r = std::sqrt(-2*std::log(y)); + a = r * std::sin(x); + b = r * std::cos(x); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Generates random vectors, uniformly distributed over the surface +/// of a sphere of given radius. +/// Input : r = sphere radius +/// Output: x,y,z a random 3-d vector of length r +/// Method: (based on algorithm suggested by Knuth and attributed to Robert E Knop) +/// which uses less random numbers than the CERNLIB RN23DIM algorithm + +void RandomFunctionsImpl<TRandomEngine>::Sphere(Double_t &x, Double_t &y, Double_t &z, Double_t r) +{ + Double_t a=0,b=0,r2=1; + while (r2 > 0.25) { + a = Rndm() - 0.5; + b = Rndm() - 0.5; + r2 = a*a + b*b; + } + z = r* ( -1. + 8.0 * r2 ); + + Double_t scale = 8.0 * r * std::sqrt(0.25 - r2); + x = a*scale; + y = b*scale; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns a uniform deviate on the interval (0, x1). + +Double_t RandomFunctionsImpl<TRandomEngine>::Uniform(Double_t x1) +{ + Double_t ans = Rndm(); + return x1*ans; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns a uniform deviate on the interval (x1, x2). + +double RandomFunctionsImpl<TRandomEngine>::Uniform(double a, double b) { + return (b-a) * Rndm() + a; +} + + + } // namespace Math +} // namespace ROOT diff --git a/ThirdParty/RootMinimizers/src/Minuit2/VariableMetricBuilder.cxx b/ThirdParty/RootMinimizers/src/Minuit2/VariableMetricBuilder.cxx index e79683ff89c..540324e0e6c 100644 --- a/ThirdParty/RootMinimizers/src/Minuit2/VariableMetricBuilder.cxx +++ b/ThirdParty/RootMinimizers/src/Minuit2/VariableMetricBuilder.cxx @@ -39,14 +39,14 @@ namespace BA_ROOT { double inner_product(const LAVector&, const LAVector&); -void VariableMetricBuilder::AddResult( std::vector<MinimumState>& result, const MinimumState & state, bool store) const { - if (!store) store = StorageLevel(); - store |= (result.size() == 0); - if (store) - result.push_back(state); - else { - result.back() = state; - } +void VariableMetricBuilder::AddResult( std::vector<MinimumState>& result, const MinimumState & state) const { + // // if (!store) store = StorageLevel(); + // // store |= (result.size() == 0); + // if (store) + result.push_back(state); + // else { + // result.back() = state; + // } if (TraceIter() ) TraceIteration(result.size()-1, result.back() ); else { if (PrintLevel() > 1) { @@ -68,6 +68,7 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC int printLevel = PrintLevel(); + #ifdef DEBUG std::cout<<"VariableMetricBuilder convergence when edm < "<<edmval<<std::endl; #endif @@ -103,7 +104,7 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC MnPrint::PrintState(std::cout, seed.State(), "VariableMetric: Initial state "); } - AddResult( result, seed.State(), true); + AddResult( result, seed.State()); // try first with a maxfxn = 80% of maxfcn @@ -157,8 +158,7 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC if (printLevel > 1) { MnPrint::PrintState(std::cout, st, "VariableMetric: After Hessian "); } - AddResult( result, st, true); - + AddResult( result, st); // check new edm edm = st.Edm(); @@ -263,10 +263,12 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC // keep also prevStep MnAlgebraicVector prevStep(initialState.Gradient().Vec().size()); + MinimumState s0 = result.back(); + assert(s0.IsValid() ); + do { - // const MinimumState& s0 = result.back(); - MinimumState s0 = result.back(); + //MinimumState s0 = result.back(); step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec(); @@ -299,20 +301,22 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC MN_INFO_VAL(gdel); #endif MnPosDef psdf; - s0 = psdf(s0, prec); - step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec(); + MinimumState s0new = psdf(s0, prec); + step = -1.*s0new.Error().InvHessian()*s0new.Gradient().Vec(); // #ifdef DEBUG // std::cout << "After MnPosdef - Error " << s0.Error().InvHessian() << " Gradient " << s0.Gradient().Vec() << " step " << step << std::endl; // #endif - gdel = inner_product(step, s0.Gradient().Grad()); + gdel = inner_product(step, s0new.Gradient().Grad()); #ifdef WARNINGMSG MN_INFO_VAL(gdel); #endif if(gdel > 0.) { - AddResult(result, s0, result.size()<=1); + AddResult(result, s0new); + return FunctionMinimum(seed, result, fcn.Up()); } } + MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec); // <= needed for case 0 <= 0 @@ -321,10 +325,12 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC MN_INFO_MSG("VariableMetricBuilder: no improvement in line search"); #endif // no improvement exit (is it really needed LM ? in vers. 1.22 tried alternative ) - // add new state where only fcn changes - AddResult(result, MinimumState(s0.Parameters(), s0.Error(), s0.Gradient(), s0.Edm(), fcn.NumOfCalls()), - result.size()<=1); - + // add new state when only fcn changes + if (result.size() <= 1 ) + AddResult(result, MinimumState(s0.Parameters(), s0.Error(), s0.Gradient(), s0.Edm(), fcn.NumOfCalls())); + else + // no need to re-store the state + AddResult(result, MinimumState(pp.Y(), s0.Edm(), fcn.NumOfCalls())); break; @@ -352,13 +358,14 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC MN_INFO_MSG("VariableMetricBuilder: matrix not pos.def. : edm is < 0. Make pos def..."); #endif MnPosDef psdf; - s0 = psdf(s0, prec); - edm = Estimator().Estimate(g, s0.Error()); + MinimumState s0new = psdf(s0, prec); + edm = Estimator().Estimate(g, s0new.Error()); if(edm < 0.) { #ifdef WARNINGMSG MN_INFO_MSG("VariableMetricBuilder: matrix still not pos.def. : exit iterations "); #endif - result.push_back(s0); + AddResult(result, s0new); + return FunctionMinimum(seed, result, fcn.Up()); } } @@ -373,7 +380,13 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC << " edm = " << edm << std::endl << std::endl; #endif - AddResult(result, MinimumState(p, e, g, edm, fcn.NumOfCalls()), result.size() <= 1); + // update the state + s0 = MinimumState(p, e, g, edm, fcn.NumOfCalls()); + if (StorageLevel() || result.size() <= 1) + AddResult(result, s0); + else + // use a reduced state for not-final iterations + AddResult(result, MinimumState(p.Fval(), edm, fcn.NumOfCalls())); // correct edm edm *= (1. + 3.*e.Dcovar()); @@ -386,6 +399,10 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn& fcn, const GradientC } while(edm > edmval && fcn.NumOfCalls() < maxfcn); // end of iteration loop + // save last result in case of no complete final states + if ( ! result.back().IsValid() ) + result.back() = s0; + if(fcn.NumOfCalls() >= maxfcn) { #ifdef WARNINGMSG diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 5d6f9f365c1..f40b7ca453d 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -5,7 +5,10 @@ # --- math packages --- find_package(Eigen3 REQUIRED) find_package(FFTW REQUIRED) -find_package(GSL 1 EXACT REQUIRED) # revert this when issue 1404 is resolved +#find_package(GSL 1 EXACT REQUIRED) # revert this when issue 1404 is resolved +find_package(GSL REQUIRED) # revert this when issue 1404 is resolved +message(INFO "XXX ${GSL_VERSION}") + # --- Boost --- set(Boost_NO_BOOST_CMAKE ON) # prevent shortcut diff --git a/dev-tools/code-tools/update_minimizers.py b/dev-tools/code-tools/update_minimizers.py index 0d4571364b7..34692da4cfe 100644 --- a/dev-tools/code-tools/update_minimizers.py +++ b/dev-tools/code-tools/update_minimizers.py @@ -5,7 +5,7 @@ from ROOT to our source tree. import os import filecmp -ROOT_SOURCE = "/home/pospelov/software/root/root-6.04.02.source" +ROOT_SOURCE = "/home/pospelov/software/root/root_v6.06.02.source" BORNAGAIN_SOURCE = "/home/pospelov/development/BornAgain/BornAgain/ThirdParty/RootMinimizers" -- GitLab