Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions README/ReleaseNotes/v642/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,31 @@ the cut instead of being selected based on `sqrt(abs(x))`.

* The `RooMinimizer::Strategy` enum has been removed. It named the Minuit strategies that are usually referred to just by integers, but caused confusion because it didn't include the unnamed "Strategy 3". Since people usually set the strategy with integer values anyway, it was decided that the simplest solution to avoid the confusion was simply to remove the `RooMinimizer::Strategy` enum

### Removal of the the constant term optimization for legacy test statistic classes
### Removal of the constant term optimization for legacy test statistic classes

The **RooFit::Optimize()** option (constant term optimization) has been deprecated in ROOT 6.40 its functionality was now removed.
The **RooFit::Optimize()** option (constant term optimization) was deprecated in ROOT 6.40, and its functionality is now removed.
The `RooFit::Optimize()` and `RooMinimizer::optimizeConst()` methods are kept for API consistency across ROOT versions, but they have no effect anymore.

This option only affected the `legacy` evaluation backend.
In practice this option only affected the `legacy` evaluation backend.

Together with the mechanism itself, the public interfaces that only existed to
drive it were removed. Code that called or overrode any of the following needs
to be adapted:

* `RooAbsArg::constOptimizeTestStatistic()`, `RooAbsArg::findConstantNodes()`,
`RooAbsArg::setCacheAndTrackHints()`, `RooAbsArg::canNodeBeCached()` and the
`RooAbsArg::ConstOpCode` and `RooAbsArg::CacheMode` enums.
* `RooAbsData::cacheArgs()`, `resetCache()`, `setArgStatus()`, `attachCache()`,
`optimizeReadingWithCaching()`, `allClientsCached()` and `hasFilledCache()`,
together with the corresponding `RooAbsDataStore` interface (`cacheArgs()`,
`cacheOwner()`, `attachCache()`, `setArgStatus()`, `resetCache()`,
`cachedVars()`, `recalculateCache()` and `forceCacheUpdate()`). Classes
deriving from `RooAbsDataStore` no longer need to implement them.
* `RooFit::TestStatistics::RooAbsL::constOptimizeTestStatistic()` and
`RooFit::TestStatistics::LikelihoodWrapper::constOptimizeTestStatistic()`.

Since the cache-and-track hints are gone, the `"CacheAndTrack"`,
`"NOCacheAndTrack"` and `"NeverConstant"` attributes no longer have any effect.

The default vectorized CPU evaluation backend (introduced in ROOT 6.32) already performs these optimizations automatically and is not affected by this change.
Users are strongly encouraged to switch to the vectorized CPU backend if they are still using the legacy backend.
Expand Down
31 changes: 0 additions & 31 deletions roofit/doc/developers/test_statistics.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,37 +147,6 @@ Make sure to also try the alternative calculation backends from the `RooFit::Eva
It will depend on your use-case which combination of options gives you the best computational performance.


## Constant term optimization
The `RooAbsTestStatistic` based classes not only combine statistics and calculation, but also constant term optimization routines.
These can be run on PDFs and datasets before starting a fit.
They search the calculation graph for parts that are independent of the fit parameters, precalculates them, and adds them to (a clone of) the dataset so that these values can be used during calculation.

In `RooFit::TestStatistics`, we separated this functionality out into the `ConstantTermsOptimizer` class.
In fact, it is not so much a class, as it is a collection of static functions that can be applied to any combination of pdf and dataset.
This class does essentially the same as `constOptimizeTestStatistic` did on a `RooNLLVar`, except that it has been factored out into a separate class.

### Usage example: apply constant term optimization on pdf and dataset inside a likelihood
Applying the default `ConstantTermsOptimizer` optimization routines on the pdf and dataset inside a `RooAbsL` likelihood is as simple as:

``` {.cpp}
likelihood.constOptimizeTestStatistic();
```
This applies constant term optimization to the cloned pdf and dataset inside the likelihood object.
It will not modify anything outside of the likelihood.

Optimization can also be activated through the minimizer, which may be more familiar to most users.
Given the `RooMinimizer` object `m` as defined in the example above, we can do:
``` {.cpp}
m.optimizeConst(2);
```

For the adventurous user, it is also possible to apply constant term optimization to a pdf and dataset directly without needing a likelihood object, e.g. given some `RooArgSet` set of observables `normSet`:
``` {.cpp}
bool applyTrackingOpt = true;
ConstantTermsOptimizer::enableConstantTermsOptimization(&pdf, &normSet, dataset, applyTrackingOpt);
```
We refer to RooFit documentation for more about "tracking optimization" which can be enabled or disabled using the final boolean parameter.

## Load balancing options

A number of calculation strategy options are available to tune load balancing.
Expand Down
131 changes: 58 additions & 73 deletions roofit/histfactory/test/testHistFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -595,82 +595,67 @@ TEST_P(HFFixtureFit, Fit)
auto mc = dynamic_cast<RooStats::ModelConfig *>(ws->obj("ModelConfig"));
ASSERT_NE(mc, nullptr);

// This tests both correct pre-caching of constant terms and (if false) that all doEval() are correct.
for (bool constTermOptimization : {true, false}) {
std::unique_ptr<RooArgSet> pars(simPdf->getParameters(*data));
// Kick parameters:
for (auto par : *pars) {
auto real = dynamic_cast<RooAbsRealLValue *>(par);
if (real && !real->isConstant())
real->setVal(real->getVal() * 0.95);
}
if (makeModelMode == MakeModelMode::StatSyst) {
auto poi = dynamic_cast<RooRealVar *>(pars->find("SigXsecOverSM"));
ASSERT_NE(poi, nullptr);
poi->setVal(2.);
poi->setConstant();
}

// constTermOptimization makes only sense in the legacy backend
if (constTermOptimization && evalBackend != RooFit::EvalBackend::Legacy()) {
continue;
}
SCOPED_TRACE(constTermOptimization ? "const term optimisation" : "No const term optimisation");

// Stop if one of the previous runs had a failure to keep the terminal clean.
if (HasFailure())
break;

std::unique_ptr<RooArgSet> pars(simPdf->getParameters(*data));
// Kick parameters:
for (auto par : *pars) {
auto real = dynamic_cast<RooAbsRealLValue *>(par);
if (real && !real->isConstant())
real->setVal(real->getVal() * 0.95);
}
if (makeModelMode == MakeModelMode::StatSyst) {
auto poi = dynamic_cast<RooRealVar *>(pars->find("SigXsecOverSM"));
ASSERT_NE(poi, nullptr);
poi->setVal(2.);
poi->setConstant();
using namespace RooFit;
std::unique_ptr<RooFitResult> fitResult{simPdf->fitTo(
*data, evalBackend, GlobalObservables(*mc->GetGlobalObservables()), Save(), PrintLevel(verbose ? 1 : -1))};
ASSERT_NE(fitResult, nullptr);
if (verbose)
fitResult->Print("v");
EXPECT_EQ(fitResult->status(), 0);

auto checkParam = [&](const std::string &param, double target, double absPrecision = 1.e-2) {
auto par = dynamic_cast<RooRealVar *>(fitResult->floatParsFinal().find(param.c_str()));
if (!par) {
// Parameter was constant in this fit
par = dynamic_cast<RooRealVar *>(fitResult->constPars().find(param.c_str()));
ASSERT_NE(par, nullptr) << param;
EXPECT_DOUBLE_EQ(par->getVal(), target) << "Constant parameter " << param << " is off target.";
} else {
EXPECT_NEAR(par->getVal(), target, par->getError())
<< "Parameter " << param << " close to target " << target << " within uncertainty";
EXPECT_NEAR(par->getVal(), target, absPrecision) << "Parameter " << param << " close to target " << target;
}
};

using namespace RooFit;
std::unique_ptr<RooFitResult> fitResult{simPdf->fitTo(*data, evalBackend, Optimize(constTermOptimization),
GlobalObservables(*mc->GetGlobalObservables()), Save(),
PrintLevel(verbose ? 1 : -1))};
ASSERT_NE(fitResult, nullptr);
if (verbose)
fitResult->Print("v");
EXPECT_EQ(fitResult->status(), 0);

auto checkParam = [&](const std::string &param, double target, double absPrecision = 1.e-2) {
auto par = dynamic_cast<RooRealVar *>(fitResult->floatParsFinal().find(param.c_str()));
if (!par) {
// Parameter was constant in this fit
par = dynamic_cast<RooRealVar *>(fitResult->constPars().find(param.c_str()));
ASSERT_NE(par, nullptr) << param;
EXPECT_DOUBLE_EQ(par->getVal(), target) << "Constant parameter " << param << " is off target.";
} else {
EXPECT_NEAR(par->getVal(), target, par->getError())
<< "Parameter " << param << " close to target " << target << " within uncertainty";
EXPECT_NEAR(par->getVal(), target, absPrecision) << "Parameter " << param << " close to target " << target;
}
};

if (makeModelMode == MakeModelMode::OverallSyst) {
// Model is set up such that background scale factors should be close to 1, and signal == 2
checkParam("SigXsecOverSM", 2.);
checkParam("alpha_syst2", 0.);
checkParam("alpha_syst3", 0.);
checkParam("alpha_syst4", 0.);
checkParam("gamma_stat_channel1_bin_0", 1.);
checkParam("gamma_stat_channel1_bin_1", 1.);
} else if (makeModelMode == MakeModelMode::HistoSyst) {
// Model is set up with a -1 sigma pull on the signal shape parameter.
checkParam("SigXsecOverSM", 2., 1.1E-1); // Higher tolerance: Expect a pull due to shape syst.
checkParam("gamma_stat_channel1_bin_0", 1.);
checkParam("gamma_stat_channel1_bin_1", 1.);
checkParam("alpha_SignalShape", -0.9, 5.E-2); // Pull slightly lower than 1 because of constraint term
} else if (makeModelMode == MakeModelMode::StatSyst) {
// Model is set up with a -1 sigma pull on the signal shape parameter.
checkParam("SigXsecOverSM", 2., 1.1E-1); // Higher tolerance: Expect a pull due to shape syst.
checkParam("gamma_stat_channel1_bin_0", 1.09); // This should be pulled
checkParam("gamma_stat_channel1_bin_1", 1.);
} else if (makeModelMode == MakeModelMode::ShapeSyst) {
// This should be pulled down
checkParam("gamma_background1Shape_bin_0", 0.8866, 0.03);
// This should be pulled up, but not so much because the free signal
// strength will fit the excess in this bin.
checkParam("gamma_background2Shape_bin_1", 1.0250, 0.03);
}
if (makeModelMode == MakeModelMode::OverallSyst) {
// Model is set up such that background scale factors should be close to 1, and signal == 2
checkParam("SigXsecOverSM", 2.);
checkParam("alpha_syst2", 0.);
checkParam("alpha_syst3", 0.);
checkParam("alpha_syst4", 0.);
checkParam("gamma_stat_channel1_bin_0", 1.);
checkParam("gamma_stat_channel1_bin_1", 1.);
} else if (makeModelMode == MakeModelMode::HistoSyst) {
// Model is set up with a -1 sigma pull on the signal shape parameter.
checkParam("SigXsecOverSM", 2., 1.1E-1); // Higher tolerance: Expect a pull due to shape syst.
checkParam("gamma_stat_channel1_bin_0", 1.);
checkParam("gamma_stat_channel1_bin_1", 1.);
checkParam("alpha_SignalShape", -0.9, 5.E-2); // Pull slightly lower than 1 because of constraint term
} else if (makeModelMode == MakeModelMode::StatSyst) {
// Model is set up with a -1 sigma pull on the signal shape parameter.
checkParam("SigXsecOverSM", 2., 1.1E-1); // Higher tolerance: Expect a pull due to shape syst.
checkParam("gamma_stat_channel1_bin_0", 1.09); // This should be pulled
checkParam("gamma_stat_channel1_bin_1", 1.);
} else if (makeModelMode == MakeModelMode::ShapeSyst) {
// This should be pulled down
checkParam("gamma_background1Shape_bin_0", 0.8866, 0.03);
// This should be pulled up, but not so much because the free signal
// strength will fit the excess in this bin.
checkParam("gamma_background2Shape_bin_1", 1.0250, 0.03);
}

if (false) {
Expand Down
2 changes: 0 additions & 2 deletions roofit/roofit/inc/RooLagrangianMorphFunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ class RooLagrangianMorphFunc : public RooAbsReal {
const char *rangeName = nullptr) const override;
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName = nullptr) const override;
void printMetaArgs(std::ostream &os) const override;
RooAbsArg::CacheMode canNodeBeCached() const override;
void setCacheAndTrackHints(RooArgSet &) override;

void insert(RooWorkspace *ws);

Expand Down
16 changes: 0 additions & 16 deletions roofit/roofit/src/RooLagrangianMorphFunc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2940,22 +2940,6 @@ void RooLagrangianMorphFunc::printMetaArgs(std::ostream &os) const
////////////////////////////////////////////////////////////////////////////////
/// Retrieve the matrix of coefficients

RooAbsArg::CacheMode RooLagrangianMorphFunc::canNodeBeCached() const
{
return this->getFunc()->canNodeBeCached();
}

////////////////////////////////////////////////////////////////////////////////
/// Retrieve the matrix of coefficients

void RooLagrangianMorphFunc::setCacheAndTrackHints(RooArgSet &arg)
{
this->getFunc()->setCacheAndTrackHints(arg);
}

////////////////////////////////////////////////////////////////////////////////
/// Retrieve the matrix of coefficients

TMatrixD RooLagrangianMorphFunc::getMatrix() const
{
auto cache = getCache();
Expand Down
2 changes: 1 addition & 1 deletion roofit/roofit/src/RooMomentMorph.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
/// coverity[UNINIT_CTOR]

RooMomentMorph::RooMomentMorph()
: _cacheMgr(this,10,true,true)
: _cacheMgr(this, 10, true, true)
{
}

Expand Down
2 changes: 1 addition & 1 deletion roofit/roofit/test/vectorisedPDFs/VectorisedPDFTests.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ std::unique_ptr<RooFitResult> PDFTest::runBatchFit(RooAbsPdf *pdf)

MyTimer batchTimer("Fitting batch mode " + _name);
std::unique_ptr<RooFitResult> result{pdf->fitTo(*_dataFit, RooFit::EvalBackend::Cpu(), RooFit::SumW2Error(false),
RooFit::Optimize(1), RooFit::PrintLevel(_printLevel), RooFit::Save(),
RooFit::PrintLevel(_printLevel), RooFit::Save(),
_multiProcess > 0 ? RooFit::NumCPU(_multiProcess) : RooCmdArg())};
std::cout << batchTimer;
EXPECT_NE(result, nullptr);
Expand Down
2 changes: 1 addition & 1 deletion roofit/roofit/test/vectorisedPDFs/testGaussBinned.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ TEST_P(GaussBinnedFit, BatchFit)
m.setVal(-1.);
s.setVal(3.);
MyTimer timer(evalBackend == EvalBackend::Value::Cpu ? "BatchBinned" : "ScalarBinned");
gaus.fitTo(*dataHist, EvalBackend(evalBackend), PrintLevel(-1), Optimize(0));
gaus.fitTo(*dataHist, EvalBackend(evalBackend), PrintLevel(-1));
timer.interval();
std::cout << timer << std::endl;
EXPECT_NEAR(m.getVal(), 1., m.getError());
Expand Down
2 changes: 0 additions & 2 deletions roofit/roofitcore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ if(roofit_multiprocess)
)
set(RooFitMPTestStatisticsHeaders
src/TestStatistics/LikelihoodGradientJob.h
src/TestStatistics/ConstantTermsOptimizer.h
src/TestStatistics/LikelihoodSerial.h
src/TestStatistics/MinuitFcnGrad.h
src/TestStatistics/LikelihoodJob.h
Expand Down Expand Up @@ -454,7 +453,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooFitCore
src/RooVectorDataStore.cxx
src/RooWorkspace.cxx
src/RooWrapperPdf.cxx
src/TestStatistics/ConstantTermsOptimizer.cxx
src/TestStatistics/LikelihoodGradientWrapper.cxx
src/TestStatistics/LikelihoodSerial.cxx
src/TestStatistics/LikelihoodWrapper.cxx
Expand Down
1 change: 0 additions & 1 deletion roofit/roofitcore/inc/RooAbsAnaConvPdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class RooAbsAnaConvPdf : public RooAbsPdf {

bool isDirectGenSafe(const RooAbsArg& arg) const override ;

void setCacheAndTrackHints(RooArgSet&) override ;

RooAbsGenContext* genContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr,
const RooArgSet* auxProto=nullptr, bool verbose= false) const override ;
Expand Down
22 changes: 0 additions & 22 deletions roofit/roofitcore/inc/RooAbsArg.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,6 @@ class RooAbsArg : public TNamed, public RooPrintable {
return false;
}

enum ConstOpCode {
Activate = 0,
DeActivate = 1,
ConfigChange = 2,
ValueChange = 3
};
enum CacheMode {
Always = 0,
NotAdvised = 1,
Never = 2
};
enum OperMode {
Auto = 0,
AClean = 1,
Expand All @@ -336,16 +325,6 @@ class RooAbsArg : public TNamed, public RooPrintable {
virtual void optimizeCacheMode(const RooArgSet &observables);
virtual void optimizeCacheMode(const RooArgSet &observables, RooArgSet &optNodes, RooLinkedList &processedNodes);

// Find constant terms in expression
bool findConstantNodes(const RooArgSet &observables, RooArgSet &cacheList);
bool findConstantNodes(const RooArgSet &observables, RooArgSet &cacheList, RooLinkedList &processedNodes);

// constant term optimization
virtual void constOptimizeTestStatistic(ConstOpCode opcode, bool doAlsoTrackingOpt = true);

virtual CacheMode canNodeBeCached() const { return Always; }
virtual void setCacheAndTrackHints(RooArgSet & /*trackNodes*/) {};

// Dirty state accessor
inline bool isShapeDirty() const
{
Expand Down Expand Up @@ -605,7 +584,6 @@ class RooAbsArg : public TNamed, public RooPrintable {
/// Attach this argument to the data store such that it reads data from there.
void attachToStore(RooAbsDataStore &store);

virtual void setTreeBranchStatus(TTree &t, bool active) = 0;
virtual void fillTreeBranch(TTree &t) = 0;
TString cleanBranchName() const;

Expand Down
1 change: 0 additions & 1 deletion roofit/roofitcore/inc/RooAbsCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class RooAbsCache {
virtual void optimizeCacheMode(const RooArgSet&, RooArgSet&, RooLinkedList& ) {}

/// Interface for constant term node finding calls.
virtual void findConstantNodes(const RooArgSet&, RooArgSet& , RooLinkedList&) {}

/// Interface for printing of cache guts in tree mode printing.
virtual void printCompactTreeHook(std::ostream&, const char *) {}
Expand Down
3 changes: 1 addition & 2 deletions roofit/roofitcore/inc/RooAbsCacheElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ class RooAbsCacheElement {
// Destructor
} ;

enum Action { OperModeChange,OptimizeCaching,FindConstantNodes } ;
enum Action { OperModeChange,OptimizeCaching } ;
virtual RooArgList containedArgs(Action) = 0 ;
/// Interface for changes of operation mode.
virtual void operModeHook(RooAbsArg::OperMode) { }
virtual void optimizeCacheMode(const RooArgSet& obs, RooArgSet& optNodes, RooLinkedList& processedNodes) ;
virtual void findConstantNodes(const RooArgSet& obs, RooArgSet& cacheList, RooLinkedList& processedNodes) ;

void setOwner(RooAbsArg* owner) {
// Store pointer to owner
Expand Down
1 change: 0 additions & 1 deletion roofit/roofitcore/inc/RooAbsCategory.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ class RooAbsCategory : public RooAbsArg {
void setCachedValue(double value, bool notifyClients = true) final;
void attachToTree(TTree& t, Int_t bufSize=32000) override ;
void attachToVStore(RooVectorDataStore& vstore) override ;
void setTreeBranchStatus(TTree& t, bool active) override ;
void fillTreeBranch(TTree& t) override ;

RooCatType* retrieveLegacyState(value_type index) const;
Expand Down
Loading
Loading