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;
101 std::vector<int> &indices = groups[arg->namePtr()];
102 if (indices.empty() || indices.back() != _nextIndex) {
103 indices.push_back(_nextIndex);
122void fillVariableGroups(
RooAbsArg const &arg, VariableGroups &out)
124 if (
auto addition =
dynamic_cast<RooAddition const *
>(&arg)) {
125 for (
RooAbsArg *component : addition->list()) {
126 fillVariableGroups(*component, out);
132 fillVariableGroups(*component, out);
136 if (
auto wrapper =
dynamic_cast<RooFit::Experimental::RooEvaluatorWrapper
const *
>(&arg)) {
137 fillVariableGroups(wrapper->topNode(), out);
150 out.registerTerm(leafList);
159 unsigned int nDim = getNDim();
162 _gradientOutput.resize(_allParams.size());
163 _multiGenFcn = std::make_unique<ROOT::Math::GradFunctor>(
this, &RooMinimizerFcn::operator(),
164 &RooMinimizerFcn::evaluateGradient, nDim);
166 _multiGenFcn = std::make_unique<ROOT::Math::Functor>(std::cref(*
this), nDim);
169 _hessianOutput.resize(_allParams.size() * _allParams.size());
174double RooMinimizerFcn::operator()(
const double *
x)
const
179 (*_logfile) <<
x[
index] <<
" ";
185 double fvalue = _funct->getVal();
188 fvalue = applyEvalErrorHandling(fvalue);
192 (*_logfile) << setprecision(15) << fvalue << setprecision(4) << std::endl;
194 std::cout <<
"\nprevFCN" << (_funct->isOffsetting() ?
"-offset" :
"") <<
" = " << setprecision(10) << fvalue
195 << setprecision(4) <<
" ";
204void RooMinimizerFcn::evaluateGradient(
const double *
x,
double *out)
const
209 (*_logfile) <<
x[
index] <<
" ";
213 _funct->gradient(_gradientOutput.data());
215 std::size_t iAll = 0;
216 std::size_t iFloating = 0;
217 for (
RooAbsArg *param : _allParamsInit) {
218 if (!treatAsConstant(*param)) {
219 out[iFloating] = _gradientOutput[iAll];
227 std::cout <<
"\n gradient = ";
228 for (std::size_t i = 0; i < getNDim(); ++i) {
229 std::cout << out[i] <<
", ";
234std::string RooMinimizerFcn::getFunctionName()
const
236 return _funct->GetName();
239std::string RooMinimizerFcn::getFunctionTitle()
const
241 return _funct->GetTitle();
244void RooMinimizerFcn::setOffsetting(
bool flag)
246 _funct->enableOffsetting(flag);
249RooArgSet RooMinimizerFcn::freezeDisconnectedParameters()
const
255 _funct->getParameters(
nullptr, paramsDisconnected,
false);
256 _funct->getParameters(
nullptr, paramsConnected,
true);
258 paramsDisconnected.
remove(paramsConnected,
true,
true);
265 if (
v && !
v->isConstant()) {
268 }
else if (cv && !cv->isConstant()) {
277bool RooMinimizerFcn::evaluateHessian(std::span<const double>
x,
double *out)
const
282 (*_logfile) <<
x[
index] <<
" ";
286 _funct->hessian(_hessianOutput.data());
288 std::size_t
m = _allParamsInit.size();
289 std::size_t
n = getNDim();
290 std::size_t iAll = 0;
291 std::size_t iFloating = 0;
292 for (
RooAbsArg *param_i : _allParamsInit) {
293 if (!treatAsConstant(*param_i)) {
294 std::size_t jAll = 0;
295 std::size_t jFloating = 0;
296 for (
RooAbsArg *param_j : _allParamsInit) {
297 if (!treatAsConstant(*param_j)) {
298 out[iFloating *
n + jFloating] = _hessianOutput[iAll *
m + jAll];
310 std::cout <<
"\n hessian = " << std::endl;
311 for (std::size_t i = 0; i < getNDim(); ++i) {
312 for (std::size_t j = 0; j < getNDim(); ++j) {
313 std::cout << out[i *
n + j] <<
", ";
315 std::cout << std::endl;
326 std::bind(&RooMinimizerFcn::evaluateHessian,
this, std::placeholders::_1, std::placeholders::_2));
333 minuit2->SetSecondDerivativeAlwaysVanishesFunc(
334 [
this](
unsigned int i,
unsigned int j) {
return secondDerivativeAlwaysVanishes(i, j); });
344void RooMinimizerFcn::buildSecondDerivMask()
const
346 VariableGroups groups;
347 fillVariableGroups(*_funct, groups);
349 std::size_t nParams = getNDim();
353 _secondDerivMask.assign(nParams * nParams,
false);
354 for (std::size_t i = 0; i < nParams; ++i) {
355 _secondDerivMask[nParams * i + i] =
true;
356 auto found1 = groups.groups.find(floatableParam(i).namePtr());
357 for (std::size_t j = 0; j < i; ++j) {
358 auto found2 = groups.groups.find(floatableParam(j).namePtr());
361 bool canBeNonZero = found1 == groups.groups.end() || found2 == groups.groups.end() ||
362 intersect(found1->second.begin(), found1->second.end(), found2->second.begin(),
363 found2->second.end());
364 _secondDerivMask[nParams * i + j] = canBeNonZero;
365 _secondDerivMask[nParams * j + i] = canBeNonZero;
375bool RooMinimizerFcn::secondDerivativeAlwaysVanishes(
unsigned int i,
unsigned int j)
const
377 std::call_once(_secondDerivMaskOnce, &RooMinimizerFcn::buildSecondDerivMask,
this);
378 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.
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)