From 4d489a740b5c0c49f15afe9711c16d0a51f2706a Mon Sep 17 00:00:00 2001 From: Lorenzo Moneta <Lorenzo.Moneta@cern.ch> Date: Fri, 1 Nov 2013 14:32:32 +0100 Subject: [PATCH] Fix math core fit tests --- math/mathcore/test/fit/WrapperRooPdf.h | 5 +- math/mathcore/test/fit/testFitPerf.cxx | 9 ++-- math/mathcore/test/fit/testMinim.cxx | 62 +++++++++++++++++-------- math/mathcore/test/fit/testRooFit.cxx | 64 +++++++++++++++++--------- 4 files changed, 96 insertions(+), 44 deletions(-) diff --git a/math/mathcore/test/fit/WrapperRooPdf.h b/math/mathcore/test/fit/WrapperRooPdf.h index 978b7c9f72d..2b8e07c5bf0 100644 --- a/math/mathcore/test/fit/WrapperRooPdf.h +++ b/math/mathcore/test/fit/WrapperRooPdf.h @@ -36,8 +36,10 @@ public: fParams = fPdf->getParameters(obsList); assert(fX!=0); assert(fParams!=0); +#ifdef DEBUG fX->Print("v"); fParams->Print("v"); +#endif } @@ -58,9 +60,10 @@ public: fParams = fPdf->getParameters(obsList); assert(fX!=0); assert(fParams!=0); +#ifdef DEBUG fX->Print("v"); fParams->Print("v"); - +#endif // // iterate on fX // TIterator* itr = fX->createIterator() ; // RooAbsArg* arg = 0; diff --git a/math/mathcore/test/fit/testFitPerf.cxx b/math/mathcore/test/fit/testFitPerf.cxx index 76a35e3b319..2ee6b0d3804 100644 --- a/math/mathcore/test/fit/testFitPerf.cxx +++ b/math/mathcore/test/fit/testFitPerf.cxx @@ -655,6 +655,9 @@ int FitUsingRooFit2(TTree * tree) { else if (j > 1) { pdf[j] = new RooProdPdf(pname.c_str(),pname.c_str(),RooArgSet(*g[j],*pdf[j-1]) ); } +// else +// pdf[0] = g[0]; + } @@ -667,7 +670,7 @@ int FitUsingRooFit2(TTree * tree) { (pdf[N-1]->getVariables())->Print("v"); // print the parameters std::cout << "\n\nDo the fit now \n\n"; #else - int level = -1; + int level = -1; bool save = false; #endif @@ -685,7 +688,7 @@ int FitUsingRooFit2(TTree * tree) { #endif - iret |= (result == 0); + iret |= (result != 0); // free for (int j = 0; j < N; ++j) { @@ -693,7 +696,7 @@ int FitUsingRooFit2(TTree * tree) { delete m[j]; delete s[j]; delete g[j]; - delete pdf[j]; + if (j> 0) delete pdf[j]; } if (iret != 0) return iret; diff --git a/math/mathcore/test/fit/testMinim.cxx b/math/mathcore/test/fit/testMinim.cxx index 2bf88a9c193..19117cd66e7 100644 --- a/math/mathcore/test/fit/testMinim.cxx +++ b/math/mathcore/test/fit/testMinim.cxx @@ -19,17 +19,19 @@ #include "TRandom3.h" #include "TMath.h" +#include "RVersion.h" + //#define DEBUG int gNCall = 0; int gNCall2 = 0; -int gNmin = 1000; -int gVerbose = 0; +int gNmin = 1; +int gVerbose = 1; bool minos = false; -double gAbsTolerance = 0.001; +double gAbsTolerance = 5.E-6; // otherwise gsl_conjugate_PR fails // Rosenbrok function to be minimize @@ -62,11 +64,15 @@ public : return new RosenBrockFunction(); } - const double * TrueMinimum() const { + const double * TrueXMinimum() const { fTrueMin[0] = 1; fTrueMin[1] = 1; return fTrueMin; } + + double TrueMinimum() const { + return 0; + } private: @@ -153,10 +159,11 @@ public : } - const double * TrueMinimum() const { + const double * TrueXMinimum() const { return x0.GetMatrixArray(); } + double TrueMinimum() const { return 0; } void Gradient (const double * x, double * g) const { gNCall2++; @@ -270,10 +277,12 @@ public : return new ChebyQuadFunction(*this); } - const double * TrueMinimum() const { + const double * TrueXMinimum() const { return &fTrueMin[0]; } + double TrueMinimum() const { return 0; } + // use equally spaced points void StartPoints(double * x, double * s) { for (unsigned int i = 0; i < fDim; ++i) { @@ -367,14 +376,24 @@ public : -const double * TrueMinimum(const ROOT::Math::IMultiGenFunction & func) { +const double * TrueXMinimum(const ROOT::Math::IMultiGenFunction & func) { + + const RosenBrockFunction * fRB = dynamic_cast< const RosenBrockFunction *> (&func); + if (fRB != 0) return fRB->TrueXMinimum(); + const TrigoFletcherFunction * fTF = dynamic_cast< const TrigoFletcherFunction *> (&func); + if (fTF != 0) return fTF->TrueXMinimum(); +// const ChebyQuadFunction * fCQ = dynamic_cast< const ChebyQuadFunction *> (&func); +// if (fCQ != 0) return fCQ->TrueXMinimum(); + return 0; +} +double TrueMinimum(const ROOT::Math::IMultiGenFunction & func) { const RosenBrockFunction * fRB = dynamic_cast< const RosenBrockFunction *> (&func); if (fRB != 0) return fRB->TrueMinimum(); const TrigoFletcherFunction * fTF = dynamic_cast< const TrigoFletcherFunction *> (&func); if (fTF != 0) return fTF->TrueMinimum(); // const ChebyQuadFunction * fCQ = dynamic_cast< const ChebyQuadFunction *> (&func); -// if (fCQ != 0) return fCQ->TrueMinimum(); +// if (fCQ != 0) return fCQ->TrueXMinimum(); return 0; } @@ -399,10 +418,11 @@ int DoNewMinimization( const ROOT::Math::IMultiGenFunction & func, const double if (func.NDim() >= 10) { min->SetMaxFunctionCalls(1000000); min->SetMaxIterations(100000); - min->SetTolerance(0.001); - if (func.NDim() >= 10) min->SetTolerance(0.01); - + min->SetTolerance(0.01); } + else + min->SetTolerance(0.001); + min->SetPrintLevel(gVerbose); // check if func provides gradient @@ -428,10 +448,11 @@ int DoNewMinimization( const ROOT::Math::IMultiGenFunction & func, const double const double * xmin = min->X(); bool ok = true; - const double * trueMin = TrueMinimum(func); + const double * trueMin = TrueXMinimum(func); if (trueMin != 0) { + ok &= (std::fabs(minval - TrueMinimum(func) ) < gAbsTolerance ); for (unsigned int i = 0; i < func.NDim(); ++i) - ok &= (std::fabs(xmin[i]-trueMin[i] ) < gAbsTolerance); + ok &= (std::fabs(xmin[i]-trueMin[i] ) < sqrt(gAbsTolerance)); } if (!ok) iret = -2; @@ -487,13 +508,15 @@ int DoOldMinimization( FCN func, TVirtualFitter * min, double &minval, double & min->GetParameter(0,parName,parx,we,al,bl); min->GetParameter(1,parName,pary,we,al,bl); - bool ok = ( TMath::Abs(parx-1.) < gAbsTolerance && - TMath::Abs(pary-1.) < gAbsTolerance ); - + bool ok = ( TMath::Abs(parx-1.) < sqrt(gAbsTolerance) && + TMath::Abs(pary-1.) < sqrt(gAbsTolerance) ); + + double errdef = 0; int nvpar, nparx; min->GetStats(minval,edm,errdef,nvpar,nparx); + if (!ok) iret = -2; min->Clear(); // for further use @@ -521,7 +544,6 @@ int testNewMinimizer( const ROOT::Math::IMultiGenFunction & func, const double * return -1; } - for (int i = 0; i < gNmin; ++i) { gNCall = 0; gNCall2 = 0; iret |= DoNewMinimization(func, x0, s0, min,minval,edm,&xmin[0]); @@ -599,10 +621,14 @@ int testRosenBrock() { // minimize using Rosenbrock Function #ifndef DEBUG - gNmin = 10000; + gNmin = 1; #endif + + +#if ROOT_VERSION_CODE < ROOT_VERSION(5,99,00) iret |= testOldMinimizer(RosenBrock,"Minuit",2); iret |= testOldMinimizer(RosenBrock,"Minuit2",2); +#endif RosenBrockFunction fRB; double xRB[2] = { -1.,1.2}; diff --git a/math/mathcore/test/fit/testRooFit.cxx b/math/mathcore/test/fit/testRooFit.cxx index 38a1cae57f7..4a7d0f993ef 100644 --- a/math/mathcore/test/fit/testRooFit.cxx +++ b/math/mathcore/test/fit/testRooFit.cxx @@ -37,11 +37,12 @@ #include "Math/WrappedParamFunction.h" #include <cmath> -const int N = 1; // n must be greater than 1 +const int N = 3; // n must be greater than 1 const int nfit = 1; const int nEvents = 10000; double iniPar[2*N]; +//#define DEBUG typedef ROOT::Math::IParamMultiFunction Func; @@ -93,10 +94,13 @@ void FillUnBinData(ROOT::Fit::UnBinData &d, TTree * tree ) { for (int j = 0; j < N; ++j) m[j] += vx[j]; } + +#ifdef DEBUG std::cout << "average values of means :\n"; for (int j = 0; j < N; ++j) std::cout << m[j]/n << " "; std::cout << "\n"; +#endif return; @@ -134,14 +138,14 @@ class MultiGaussRooPdf { g[j] = new RooGaussian(gname.c_str(),"gauss(x,mean,sigma)",*x[j],*m[j],*s[j]); std::string pname = "prod_" + ROOT::Math::Util::ToString(j); - if (j == 1) { + if (j == 0) + pdf[0] = g[0]; + else if (j == 1) { pdf[1] = new RooProdPdf(pname.c_str(),pname.c_str(),RooArgSet(*g[1],*g[0]) ); } else if (j > 1) { pdf[j] = new RooProdPdf(pname.c_str(),pname.c_str(),RooArgSet(*g[j],*pdf[j-1]) ); } - else if (j == 0) - pdf[0] = g[0]; } @@ -164,7 +168,7 @@ class MultiGaussRooPdf { delete m[j]; delete s[j]; delete g[j]; - delete pdf[j]; + if (j> 0) delete pdf[j]; // no pdf allocated for j = 0 } } @@ -199,13 +203,13 @@ int FitUsingRooFit(TTree & tree, RooAbsPdf & pdf, RooArgSet & xvars) { #ifdef DEBUG - int level = 3; + int level = 2; std::cout << "num entries = " << data.numEntries() << std::endl; bool save = true; - (pdf[N-1]->getVariables())->Print("v"); // print the parameters + pdf.getVariables()->Print("v"); // print the parameters std::cout << "\n\nDo the fit now \n\n"; #else - int level = 1; + int level = -1; bool save = false; #endif @@ -226,6 +230,7 @@ int FitUsingRooFit(TTree & tree, RooAbsPdf & pdf, RooArgSet & xvars) { w.Stop(); + std::cout << "RooFit result " << std::endl; RooArgSet * params = pdf.getParameters(xvars); params->Print("v"); delete params; @@ -248,7 +253,7 @@ int DoFit(TTree * tree, Func & func, bool debug = false, bool = false ) { //std::cout << "Fit parameter 2 " << f.Parameters()[2] << std::endl; ROOT::Fit::Fitter fitter; - fitter.Config().MinimizerOptions().SetPrintLevel(2); + fitter.Config().MinimizerOptions().SetPrintLevel(0); fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str()); fitter.Config().MinimizerOptions().SetTolerance(1.); // to be consistent with RooFit @@ -267,8 +272,7 @@ int DoFit(TTree * tree, Func & func, bool debug = false, bool = false ) { std::cout << " Fit Failed " << std::endl; return -1; } - if (debug) - fitter.Result().Print(std::cout); + fitter.Result().Print(std::cout); return 0; } @@ -301,13 +305,29 @@ int FitUsingNewFitter(FitObj * fitobj, Func & func, bool useGrad=false) { return iret; } -double gausnorm(const double *x, const double *p) { - //return p[0]*TMath::Gaus(x[0],p[1],p[2]); - double invsig = 1./p[1]; - double tmp = (x[0]-p[0]) * invsig; - const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); - return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; -} +template <int N> +struct GausNorm { + static double F(const double *x, const double *p) { + return ROOT::Math::normal_pdf(x[N-1], p[2*N-1], p[2*N-2] ) * GausNorm<N-1>::F(x,p); + } +}; +template <> +struct GausNorm<1> { + + static double F(const double *x, const double *p) { + return ROOT::Math::normal_pdf(x[0], p[1], p[0] ); + } +}; + + +// double gausnorm( +// return ROOT::Math::normal_pdf(x[0], p[1], p[0] ); +// // //return p[0]*TMath::Gaus(x[0],p[1],p[2]); +// // double invsig = 1./p[1]; +// // double tmp = (x[0]-p[0]) * invsig; +// // const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); +// // return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; +// } @@ -346,10 +366,10 @@ int main() { // in case of N = 1 do also a simple gauss fit // using TF1 gausN - if (N == 1) { - ROOT::Math::WrappedParamFunction<> gausn(&gausnorm,2,iniPar,iniPar+1); - FitUsingNewFitter<TMINUIT>(&tree,gausn); - } +// if (N == 1) { + ROOT::Math::WrappedParamFunction<> gausn(&GausNorm<N>::F,2*N,iniPar,iniPar+2*N); + FitUsingNewFitter<TMINUIT>(&tree,gausn); + //} -- GitLab