43#include <unordered_map>
46using std::setprecision;
53template <
class InputIt1,
class InputIt2>
54bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
56 while (first1 != last1 && first2 != last2) {
57 if (*first1 < *first2) {
61 if (*first2 < *first1) {
89struct VariableGroups {
92 std::unordered_map<TNamed const *, std::vector<int>> groups;
99 groups[arg->namePtr()].push_back(_nextIndex);
117void fillVariableGroups(
RooAbsArg const &arg, VariableGroups &out)
119 if (
auto addition =
dynamic_cast<RooAddition const *
>(&arg)) {
120 for (
RooAbsArg *component : addition->list()) {
121 fillVariableGroups(*component, out);
127 fillVariableGroups(*component, out);
131 if (
auto wrapper =
dynamic_cast<RooFit::Experimental::RooEvaluatorWrapper
const *
>(&arg)) {
132 fillVariableGroups(wrapper->topNode(), out);
143 out.registerTerm(leafSet);
152 unsigned int nDim = getNDim();
155 _gradientOutput.resize(_allParams.size());
156 _multiGenFcn = std::make_unique<ROOT::Math::GradFunctor>(
this, &RooMinimizerFcn::operator(),
157 &RooMinimizerFcn::evaluateGradient, nDim);
159 _multiGenFcn = std::make_unique<ROOT::Math::Functor>(std::cref(*
this), nDim);
162 _hessianOutput.resize(_allParams.size() * _allParams.size());
167double RooMinimizerFcn::operator()(
const double *
x)
const
172 (*_logfile) <<
x[
index] <<
" ";
178 double fvalue = _funct->getVal();
181 fvalue = applyEvalErrorHandling(fvalue);
185 (*_logfile) << setprecision(15) << fvalue << setprecision(4) << std::endl;
187 std::cout <<
"\nprevFCN" << (_funct->isOffsetting() ?
"-offset" :
"") <<
" = " << setprecision(10) << fvalue
188 << setprecision(4) <<
" ";
197void RooMinimizerFcn::evaluateGradient(
const double *
x,
double *out)
const
202 (*_logfile) <<
x[
index] <<
" ";
206 _funct->gradient(_gradientOutput.data());
208 std::size_t iAll = 0;
209 std::size_t iFloating = 0;
210 for (
RooAbsArg *param : _allParamsInit) {
211 if (!treatAsConstant(*param)) {
212 out[iFloating] = _gradientOutput[iAll];
220 std::cout <<
"\n gradient = ";
221 for (std::size_t i = 0; i < getNDim(); ++i) {
222 std::cout << out[i] <<
", ";
227std::string RooMinimizerFcn::getFunctionName()
const
229 return _funct->GetName();
232std::string RooMinimizerFcn::getFunctionTitle()
const
234 return _funct->GetTitle();
237void RooMinimizerFcn::setOffsetting(
bool flag)
239 _funct->enableOffsetting(flag);
242RooArgSet RooMinimizerFcn::freezeDisconnectedParameters()
const
248 _funct->getParameters(
nullptr, paramsDisconnected,
false);
249 _funct->getParameters(
nullptr, paramsConnected,
true);
251 paramsDisconnected.
remove(paramsConnected,
true,
true);
258 if (
v && !
v->isConstant()) {
261 }
else if (cv && !cv->isConstant()) {
270bool RooMinimizerFcn::evaluateHessian(std::span<const double>
x,
double *out)
const
275 (*_logfile) <<
x[
index] <<
" ";
279 _funct->hessian(_hessianOutput.data());
281 std::size_t
m = _allParamsInit.size();
282 std::size_t
n = getNDim();
283 std::size_t iAll = 0;
284 std::size_t iFloating = 0;
285 for (
RooAbsArg *param_i : _allParamsInit) {
286 if (!treatAsConstant(*param_i)) {
287 std::size_t jAll = 0;
288 std::size_t jFloating = 0;
289 for (
RooAbsArg *param_j : _allParamsInit) {
290 if (!treatAsConstant(*param_j)) {
291 out[iFloating *
n + jFloating] = _hessianOutput[iAll *
m + jAll];
303 std::cout <<
"\n hessian = " << std::endl;
304 for (std::size_t i = 0; i < getNDim(); ++i) {
305 for (std::size_t j = 0; j < getNDim(); ++j) {
306 std::cout << out[i *
n + j] <<
", ";
308 std::cout << std::endl;
319 std::bind(&RooMinimizerFcn::evaluateHessian,
this, std::placeholders::_1, std::placeholders::_2));
326 minuit2->SetSecondDerivativeAlwaysVanishesFunc(
327 [
this](
unsigned int i,
unsigned int j) {
return secondDerivativeAlwaysVanishes(i, j); });
337void RooMinimizerFcn::buildSecondDerivMask()
const
339 VariableGroups groups;
340 fillVariableGroups(*_funct, groups);
342 std::size_t nParams = getNDim();
346 _secondDerivMask.assign(nParams * nParams,
false);
347 for (std::size_t i = 0; i < nParams; ++i) {
348 _secondDerivMask[nParams * i + i] =
true;
349 auto found1 = groups.groups.find(floatableParam(i).namePtr());
350 for (std::size_t j = 0; j < i; ++j) {
351 auto found2 = groups.groups.find(floatableParam(j).namePtr());
354 bool canBeNonZero = found1 == groups.groups.end() || found2 == groups.groups.end() ||
355 intersect(found1->second.begin(), found1->second.end(), found2->second.begin(),
356 found2->second.end());
357 _secondDerivMask[nParams * i + j] = canBeNonZero;
358 _secondDerivMask[nParams * j + i] = canBeNonZero;
368bool RooMinimizerFcn::secondDerivativeAlwaysVanishes(
unsigned int i,
unsigned int j)
const
370 std::call_once(_secondDerivMaskOnce, &RooMinimizerFcn::buildSecondDerivMask,
this);
371 return !_secondDerivMask[getNDim() * i + j];
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Abstract Minimizer class, defining the interface for the various minimizer (like Minuit2,...
virtual void SetHessianFunction(std::function< bool(std::span< const double >, double *)>)
Set the function implementing Hessian computation (re-implemented by Minimizer using it).
virtual void SetFunction(const ROOT::Math::IMultiGenFunction &func)=0
Set the function to minimize.
Minuit2Minimizer class implementing the ROOT::Math::Minimizer interface for Minuit2 minimization algo...
Common abstract base class for objects that represent a value and a "shape" in RooFit.
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
void treeNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool doBranch=true, bool doLeaf=true, bool valueOnly=false, bool recurseNonDerived=false) const
Fill supplied list with nodes of the arg tree, following all server links, starting with ourself as t...
void setConstant(bool value=true)
Abstract container object that can hold multiple RooAbsArg objects.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
const_iterator end() const
const_iterator begin() const
Abstract base class for objects that represent a real value and implements functionality common to al...
virtual bool hasGradient() const
static void setHideOffset(bool flag)
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Object to represent discrete states.
Calculates the sum of the -(log) likelihoods of a set of RooAbsPfs that represent constraint function...
Wrapper class around ROOT::Math::Minimizer that provides a seamless interface between the minimizer f...
RooMinimizer::Config _cfg
Variable that can be changed from the outside.
double constraintSum(DoubleArray comp, unsigned int compSize)