Skip to content

Commit a79ccd5

Browse files
committed
[RF] Test RooFit Hessians with Clad
1 parent 0e45a9e commit a79ccd5

2 files changed

Lines changed: 35 additions & 13 deletions

File tree

roofit/histfactory/test/testHistFactory.cxx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99
#include <RooFitHS3/JSONIO.h>
1010
#include <RooFitHS3/RooJSONFactoryWSTool.h>
1111

12-
#include <RooFit/Detail/NormalizationHelpers.h>
13-
#include <RooDataHist.h>
14-
#include <RooWorkspace.h>
1512
#include <RooArgSet.h>
16-
#include <RooSimultaneous.h>
17-
#include <RooRealSumPdf.h>
18-
#include <RooRealVar.h>
19-
#include <RooHelpers.h>
13+
#include <RooDataHist.h>
14+
#include <RooEvaluatorWrapper.h>
15+
#include <RooFit/Detail/NormalizationHelpers.h>
16+
#include <RooFit/Evaluator.h>
2017
#include <RooFitResult.h>
18+
#include <RooHelpers.h>
19+
#include <RooMinimizer.h>
2120
#include <RooPlot.h>
22-
#include <RooFit/Evaluator.h>
21+
#include <RooRealSumPdf.h>
22+
#include <RooRealVar.h>
23+
#include <RooSimultaneous.h>
24+
#include <RooWorkspace.h>
2325

2426
#include <TROOT.h>
2527
#include <TFile.h>
@@ -618,9 +620,21 @@ TEST_P(HFFixtureFit, Fit)
618620
}
619621

620622
using namespace RooFit;
621-
std::unique_ptr<RooFitResult> fitResult{simPdf->fitTo(*data, evalBackend, Optimize(constTermOptimization),
622-
GlobalObservables(*mc->GetGlobalObservables()), Save(),
623-
PrintLevel(verbose ? 1 : -1))};
623+
std::unique_ptr<RooAbsReal> nll{simPdf->createNLL(*data, evalBackend, Optimize(constTermOptimization),
624+
GlobalObservables(*mc->GetGlobalObservables()))};
625+
RooMinimizer::Config cfg;
626+
if (evalBackend == RooFit::EvalBackend::Codegen()) {
627+
// Make sure we use both analytical gradient and Hessian
628+
static_cast<RooFit::Experimental::RooEvaluatorWrapper &>(*nll).generateGradient();
629+
static_cast<RooFit::Experimental::RooEvaluatorWrapper &>(*nll).generateHessian();
630+
cfg.useGradient = true;
631+
cfg.useHessian = true;
632+
}
633+
RooMinimizer minim{*nll, cfg};
634+
minim.setPrintLevel(verbose ? 1 : -1);
635+
minim.minimize("Minuit2", "Migrad");
636+
minim.hesse();
637+
std::unique_ptr<RooFitResult> fitResult{minim.save()};
624638
ASSERT_NE(fitResult, nullptr);
625639
if (verbose)
626640
fitResult->Print("v");

roofit/roofitcore/test/testRooFuncWrapper.cxx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,16 @@ class FactoryTest : public testing::TestWithParam<FactoryTestParams> {
129129
std::unique_ptr<RooHelpers::LocalChangeMsgLevel> _changeMsgLvl;
130130
};
131131

132-
std::unique_ptr<RooFitResult> runMinimizer(RooAbsReal &absReal, bool useGradient = true)
132+
std::unique_ptr<RooFitResult> runMinimizer(RooAbsReal &absReal, bool useAD = true)
133133
{
134134
RooMinimizer::Config cfg;
135-
cfg.useGradient = useGradient;
135+
cfg.useGradient = useAD;
136+
cfg.useHessian = useAD;
136137
RooMinimizer m{absReal, cfg};
137138
m.setPrintLevel(-1);
138139
m.setStrategy(0);
139140
m.minimize("Minuit2");
141+
m.hesse(); // to use the analytical Hessian for error estimation
140142
return std::unique_ptr<RooFitResult>{m.save()};
141143
}
142144

@@ -164,6 +166,9 @@ TEST_P(FactoryTest, NLLFit)
164166
// We want to use the generated code also for the nominal likelihood. Like
165167
// this, we make sure to validate also the NLL values of the generated code.
166168
static_cast<RooFit::Experimental::RooEvaluatorWrapper &>(*nllFunc).setUseGeneratedFunctionCode(true);
169+
// Let's also validate the Hessian
170+
static_cast<RooFit::Experimental::RooEvaluatorWrapper&>(*nllFunc).generateHessian();
171+
static_cast<RooFit::Experimental::RooEvaluatorWrapper&>(*nllFunc).writeDebugMacro(_params._name);
167172

168173
double tol = _params._fitResultTolerance;
169174

@@ -214,6 +219,9 @@ TEST_P(FactoryTest, NLLFit)
214219
// because for very small correlations it's usually not the same within the
215220
// relative tolerance because you would compare two small values that are
216221
// only different from zero because of noise.
222+
// The error tolerance is also quite large, because the analytical Hessian
223+
// gives numerically quite different results.
224+
double errorTol = 0.1;
217225
EXPECT_TRUE(result->isIdenticalNoCov(*resultRef, tol, tol));
218226
EXPECT_TRUE(resultAd->isIdenticalNoCov(*resultRef, tol, tol));
219227
}

0 commit comments

Comments
 (0)