Logo ROOT  
Reference Guide
RooAbsMinimizerFcn.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * AL, Alfio Lazzaro, INFN Milan, alfio.lazzaro@mi.infn.it *
7 * PB, Patrick Bos, Netherlands eScience Center, p.bos@esciencecenter.nl *
8 * *
9 * *
10 * Redistribution and use in source and binary forms, *
11 * with or without modification, are permitted according to the terms *
12 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
13 *****************************************************************************/
14
15//////////////////////////////////////////////////////////////////////////////
16//
17// RooAbsMinimizerFcn is an interface class to the ROOT::Math function
18// for minimization. It contains only the "logistics" of synchronizing
19// between Minuit and RooFit. Its subclasses implement actual interfacing
20// to Minuit by subclassing IMultiGenFunction or IMultiGradFunction.
21//
22
23#include "RooAbsMinimizerFcn.h"
24
25#include "RooAbsArg.h"
26#include "RooAbsPdf.h"
27#include "RooArgSet.h"
28#include "RooDataSet.h"
29#include "RooRealVar.h"
30#include "RooAbsRealLValue.h"
31#include "RooMsgService.h"
32#include "RooMinimizer.h"
33#include "RooNaNPacker.h"
34
35#include "TClass.h"
36#include "TMatrixDSym.h"
37
38#include <fstream>
39#include <iomanip>
40
41using namespace std;
42
44 : _context(context), _verbose(verbose)
45{
46 // Examine parameter list
47 _floatParamList.reset((RooArgList *)paramList.selectByAttrib("Constant", false));
48 if (_floatParamList->getSize() > 1) {
49 _floatParamList->sort();
50 }
51 _floatParamList->setName("floatParamList");
52
53 _constParamList.reset((RooArgList *)paramList.selectByAttrib("Constant", true));
54 if (_constParamList->getSize() > 1) {
55 _constParamList->sort();
56 }
57 _constParamList->setName("constParamList");
58
59 // Remove all non-RooRealVar parameters from list (MINUIT cannot handle them)
60 for (unsigned int i = 0; i < _floatParamList->size(); ) { // Note: Counting loop, since removing from collection!
61 const RooAbsArg* arg = (*_floatParamList).at(i);
63 oocoutW(_context,Minimization) << "RooAbsMinimizerFcn::RooAbsMinimizerFcn: removing parameter "
64 << arg->GetName() << " from list because it is not of type RooRealVar" << endl;
65 _floatParamList->remove(*arg);
66 } else {
67 ++i;
68 }
69 }
70
71 _nDim = _floatParamList->getSize();
72
73 // Save snapshot of initial lists
74 _initFloatParamList.reset((RooArgList *)_floatParamList->snapshot(false));
75 _initConstParamList.reset((RooArgList *)_constParamList->snapshot(false));
76}
77
79 : _context(other._context), _maxFCN(other._maxFCN),
80 _funcOffset(other._funcOffset),
81 _recoverFromNaNStrength(other._recoverFromNaNStrength),
82 _numBadNLL(other._numBadNLL),
83 _printEvalErrors(other._printEvalErrors), _evalCounter(other._evalCounter),
84 _nDim(other._nDim), _optConst(other._optConst),
85 _floatParamList(new RooArgList(*other._floatParamList)), _constParamList(new RooArgList(*other._constParamList)),
86 _initFloatParamList((RooArgList *)other._initFloatParamList->snapshot(false)),
87 _initConstParamList((RooArgList *)other._initConstParamList->snapshot(false)),
88 _logfile(other._logfile), _doEvalErrorWall(other._doEvalErrorWall), _verbose(other._verbose)
89{}
90
91
92/// Internal function to synchronize TMinimizer with current
93/// information in RooAbsReal function parameters
94bool RooAbsMinimizerFcn::synchronizeParameterSettings(std::vector<ROOT::Fit::ParameterSettings> &parameters, bool optConst, bool verbose)
95{
96 bool constValChange(false);
97 bool constStatChange(false);
98
99 Int_t index(0);
100
101 // Handle eventual migrations from constParamList -> floatParamList
102 for (index = 0; index < _constParamList->getSize(); index++) {
103
104 RooRealVar *par = dynamic_cast<RooRealVar *>(_constParamList->at(index));
105 if (!par)
106 continue;
107
108 RooRealVar *oldpar = dynamic_cast<RooRealVar *>(_initConstParamList->at(index));
109 if (!oldpar)
110 continue;
111
112 // Test if constness changed
113 if (!par->isConstant()) {
114
115 // Remove from constList, add to floatList
116 _constParamList->remove(*par);
117 _floatParamList->add(*par);
118 _initFloatParamList->addClone(*oldpar);
119 _initConstParamList->remove(*oldpar);
120 constStatChange = true;
121 _nDim++;
122
123 if (verbose) {
125 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now floating." << endl;
126 }
127 }
128
129 // Test if value changed
130 if (par->getVal() != oldpar->getVal()) {
131 constValChange = true;
132 if (verbose) {
134 << "RooAbsMinimizerFcn::synchronize: value of constant parameter " << par->GetName() << " changed from "
135 << oldpar->getVal() << " to " << par->getVal() << endl;
136 }
137 }
138 }
139
140 // Update reference list
142
143 // Synchronize MINUIT with function state
144 // Handle floatParamList
145 for (index = 0; index < _floatParamList->getSize(); index++) {
146 RooRealVar *par = dynamic_cast<RooRealVar *>(_floatParamList->at(index));
147
148 if (!par)
149 continue;
150
151 double pstep(0);
152 double pmin(0);
153 double pmax(0);
154
155 if (!par->isConstant()) {
156
157 // Verify that floating parameter is indeed of type RooRealVar
158 if (!par->IsA()->InheritsFrom(RooRealVar::Class())) {
159 oocoutW(_context, Minimization) << "RooAbsMinimizerFcn::fit: Error, non-constant parameter "
160 << par->GetName() << " is not of type RooRealVar, skipping" << endl;
161 _floatParamList->remove(*par);
162 index--;
163 _nDim--;
164 continue;
165 }
166 // make sure the parameter are in dirty state to enable
167 // a real NLL computation when the minimizer calls the function the first time
168 // (see issue #7659)
169 par->setValueDirty();
170
171 // Set the limits, if not infinite
172 if (par->hasMin())
173 pmin = par->getMin();
174 if (par->hasMax())
175 pmax = par->getMax();
176
177 // Calculate step size
178 pstep = par->getError();
179 if (pstep <= 0) {
180 // Floating parameter without error estitimate
181 if (par->hasMin() && par->hasMax()) {
182 pstep = 0.1 * (pmax - pmin);
183
184 // Trim default choice of error if within 2 sigma of limit
185 if (pmax - par->getVal() < 2 * pstep) {
186 pstep = (pmax - par->getVal()) / 2;
187 } else if (par->getVal() - pmin < 2 * pstep) {
188 pstep = (par->getVal() - pmin) / 2;
189 }
190
191 // If trimming results in zero error, restore default
192 if (pstep == 0) {
193 pstep = 0.1 * (pmax - pmin);
194 }
195
196 } else {
197 pstep = 1;
198 }
199 if (verbose) {
201 << "RooAbsMinimizerFcn::synchronize: WARNING: no initial error estimate available for "
202 << par->GetName() << ": using " << pstep << endl;
203 }
204 }
205 } else {
206 pmin = par->getVal();
207 pmax = par->getVal();
208 }
209
210 // new parameter
211 if (index >= Int_t(parameters.size())) {
212
213 if (par->hasMin() && par->hasMax()) {
214 parameters.emplace_back(par->GetName(), par->getVal(), pstep, pmin, pmax);
215 } else {
216 parameters.emplace_back(par->GetName(), par->getVal(), pstep);
217 if (par->hasMin())
218 parameters.back().SetLowerLimit(pmin);
219 else if (par->hasMax())
220 parameters.back().SetUpperLimit(pmax);
221 }
222
223 continue;
224 }
225
226 bool oldFixed = parameters[index].IsFixed();
227 double oldVar = parameters[index].Value();
228 double oldVerr = parameters[index].StepSize();
229 double oldVlo = parameters[index].LowerLimit();
230 double oldVhi = parameters[index].UpperLimit();
231
232 if (par->isConstant() && !oldFixed) {
233
234 // Parameter changes floating -> constant : update only value if necessary
235 if (oldVar != par->getVal()) {
236 parameters[index].SetValue(par->getVal());
237 if (verbose) {
239 << "RooAbsMinimizerFcn::synchronize: value of parameter " << par->GetName() << " changed from "
240 << oldVar << " to " << par->getVal() << endl;
241 }
242 }
243 parameters[index].Fix();
244 constStatChange = true;
245 if (verbose) {
247 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now fixed." << endl;
248 }
249
250 } else if (par->isConstant() && oldFixed) {
251
252 // Parameter changes constant -> constant : update only value if necessary
253 if (oldVar != par->getVal()) {
254 parameters[index].SetValue(par->getVal());
255 constValChange = true;
256
257 if (verbose) {
259 << "RooAbsMinimizerFcn::synchronize: value of fixed parameter " << par->GetName() << " changed from "
260 << oldVar << " to " << par->getVal() << endl;
261 }
262 }
263
264 } else {
265 // Parameter changes constant -> floating
266 if (!par->isConstant() && oldFixed) {
267 parameters[index].Release();
268 constStatChange = true;
269
270 if (verbose) {
272 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now floating." << endl;
273 }
274 }
275
276 // Parameter changes constant -> floating : update all if necessary
277 if (oldVar != par->getVal() || oldVlo != pmin || oldVhi != pmax || oldVerr != pstep) {
278 parameters[index].SetValue(par->getVal());
279 parameters[index].SetStepSize(pstep);
280 if (par->hasMin() && par->hasMax())
281 parameters[index].SetLimits(pmin, pmax);
282 else if (par->hasMin())
283 parameters[index].SetLowerLimit(pmin);
284 else if (par->hasMax())
285 parameters[index].SetUpperLimit(pmax);
286 }
287
288 // Inform user about changes in verbose mode
289 if (verbose) {
290 // if ierr<0, par was moved from the const list and a message was already printed
291
292 if (oldVar != par->getVal()) {
294 << "RooAbsMinimizerFcn::synchronize: value of parameter " << par->GetName() << " changed from "
295 << oldVar << " to " << par->getVal() << endl;
296 }
297 if (oldVlo != pmin || oldVhi != pmax) {
299 << "RooAbsMinimizerFcn::synchronize: limits of parameter " << par->GetName() << " changed from ["
300 << oldVlo << "," << oldVhi << "] to [" << pmin << "," << pmax << "]" << endl;
301 }
302
303 // If oldVerr=0, then parameter was previously fixed
304 if (oldVerr != pstep && oldVerr != 0) {
306 << "RooAbsMinimizerFcn::synchronize: error/step size of parameter " << par->GetName()
307 << " changed from " << oldVerr << " to " << pstep << endl;
308 }
309 }
310 }
311 }
312
313 if (optConst) {
314 optimizeConstantTerms(constStatChange, constValChange);
315 }
316
317 return 0;
318}
319
320bool
321RooAbsMinimizerFcn::Synchronize(std::vector<ROOT::Fit::ParameterSettings> &parameters, bool optConst, bool verbose) {
322 return synchronizeParameterSettings(parameters, optConst, verbose);
323}
324
325/// Modify PDF parameter error by ordinal index (needed by MINUIT)
327{
328 static_cast<RooRealVar*>(_floatParamList->at(index))->setError(value);
329}
330
331/// Modify PDF parameter error by ordinal index (needed by MINUIT)
333{
334 static_cast<RooRealVar*>(_floatParamList->at(index))->removeAsymError();
335}
336
337/// Modify PDF parameter error by ordinal index (needed by MINUIT)
338void RooAbsMinimizerFcn::SetPdfParamErr(Int_t index, double loVal, double hiVal)
339{
340 static_cast<RooRealVar*>(_floatParamList->at(index))->setAsymError(loVal, hiVal);
341}
342
343/// Transfer MINUIT fit results back into RooFit objects.
345{
346 for (unsigned int index = 0; index < _nDim; index++) {
347 double value = results.Value(index);
349
350 // Set the parabolic error
351 double err = results.Error(index);
352 SetPdfParamErr(index, err);
353
354 double eminus = results.LowerError(index);
355 double eplus = results.UpperError(index);
356
357 if (eplus > 0 || eminus < 0) {
358 // Store the asymmetric error, if it is available
359 SetPdfParamErr(index, eminus, eplus);
360 } else {
361 // Clear the asymmetric error
363 }
364 }
365}
366
367/// Change the file name for logging of a RooMinimizer of all MINUIT steppings
368/// through the parameter space. If inLogfile is null, the current log file
369/// is closed and logging is stopped.
370bool RooAbsMinimizerFcn::SetLogFile(const char *inLogfile)
371{
372 if (_logfile) {
373 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setLogFile: closing previous log file" << endl;
374 _logfile->close();
375 delete _logfile;
376 _logfile = 0;
377 }
378 _logfile = new ofstream(inLogfile);
379 if (!_logfile->good()) {
380 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setLogFile: cannot open file " << inLogfile << endl;
381 _logfile->close();
382 delete _logfile;
383 _logfile = 0;
384 }
385
386 return false;
387}
388
389/// Apply results of given external covariance matrix. i.e. propagate its errors
390/// to all RRV parameter representations and give this matrix instead of the
391/// HESSE matrix at the next save() call
393{
394 for (unsigned int i = 0; i < _nDim; i++) {
395 // Skip fixed parameters
396 if (_floatParamList->at(i)->isConstant()) {
397 continue;
398 }
399 SetPdfParamErr(i, sqrt(V(i, i)));
400 }
401}
402
403/// Set value of parameter i.
405{
406 auto par = static_cast<RooRealVar*>(&(*_floatParamList)[index]);
407
408 if (par->getVal()!=value) {
409 if (_verbose) cout << par->GetName() << "=" << value << ", " ;
410
411 par->setVal(value);
412 return true;
413 }
414
415 return false;
416}
417
418
419/// Print information about why evaluation failed.
420/// Using _printEvalErrors, the number of errors printed can be steered.
421/// Negative values disable printing.
423 if (_printEvalErrors < 0)
424 return;
425
426 std::ostringstream msg;
427 if (_doEvalErrorWall) {
428 msg << "RooAbsMinimizerFcn: Minimized function has error status." << endl
429 << "Returning maximum FCN so far (" << _maxFCN
430 << ") to force MIGRAD to back out of this region. Error log follows.\n";
431 } else {
432 msg << "RooAbsMinimizerFcn: Minimized function has error status but is ignored.\n";
433 }
434
435 msg << "Parameter values: " ;
436 for (const auto par : *_floatParamList) {
437 auto var = static_cast<const RooRealVar*>(par);
438 msg << "\t" << var->GetName() << "=" << var->getVal() ;
439 }
440 msg << std::endl;
441
443 ooccoutW(_context,Minimization) << msg.str() << endl;
444}
445
446
448
450
451 if(!_context->_logDataSet) {
452 const char* name = "minimizer_log_dataset";
453 _context->_logDataSet = std::make_unique<RooDataSet>(name, name, *_floatParamList);
454 }
455
457 }
458
459 _evalCounter++;
460}
461
462
464{
466
467 if (_optConst && !flag) {
468 if (_context->getPrintLevel() > -1)
469 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization" << endl;
471 _optConst = flag;
472 } else if (!_optConst && flag) {
473 if (_context->getPrintLevel() > -1)
474 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: activating const optimization" << endl;
476 _optConst = flag;
477 } else if (_optConst && flag) {
478 if (_context->getPrintLevel() > -1)
479 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: const optimization already active" << endl;
480 } else {
481 if (_context->getPrintLevel() > -1)
482 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: const optimization wasn't active" << endl;
483 }
484
486}
487
488void RooAbsMinimizerFcn::optimizeConstantTerms(bool constStatChange, bool constValChange) {
489 if (constStatChange) {
490
492
493 oocoutI(_context,Minimization) << "RooAbsMinimizerFcn::optimizeConstantTerms: set of constant parameters changed, rerunning const optimizer" << endl ;
495 } else if (constValChange) {
496 oocoutI(_context,Minimization) << "RooAbsMinimizerFcn::optimizeConstantTerms: constant parameter values changed, rerunning const optimizer" << endl ;
498 }
499
501}
502
503std::vector<double> RooAbsMinimizerFcn::getParameterValues() const
504{
505 // TODO: make a cache for this somewhere so it doesn't have to be recreated on each call
506 std::vector<double> values;
507 values.reserve(_nDim);
508
509 for (std::size_t index = 0; index < _nDim; ++index) {
511 values.push_back(par->getVal());
512 }
513
514 return values;
515}
#define oocoutW(o, a)
Definition: RooMsgService.h:51
#define oocoutI(o, a)
Definition: RooMsgService.h:49
#define ooccoutW(o, a)
Definition: RooMsgService.h:59
int Int_t
Definition: RtypesCore.h:45
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition: TGX11.cxx:110
class containing the result of the fit and all the related information (fitted parameter values,...
Definition: FitResult.h:47
double UpperError(unsigned int i) const
upper Minos error. If Minos has not run for parameter i return the parabolic error
Definition: FitResult.cxx:328
double Error(unsigned int i) const
parameter error by index
Definition: FitResult.h:177
double Value(unsigned int i) const
parameter value by index
Definition: FitResult.h:170
double LowerError(unsigned int i) const
lower Minos error. If Minos has not run for parameter i return the parabolic error
Definition: FitResult.cxx:321
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition: RooAbsArg.h:71
bool isConstant() const
Check if the "Constant" attribute is set.
Definition: RooAbsArg.h:362
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition: RooAbsArg.h:490
@ DeActivate
Definition: RooAbsArg.h:388
@ ValueChange
Definition: RooAbsArg.h:388
@ ConfigChange
Definition: RooAbsArg.h:388
RooAbsCollection * selectByAttrib(const char *name, bool value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
void setOptimizeConst(Int_t flag)
RooMinimizer * _context
std::unique_ptr< RooArgList > _floatParamList
bool SetLogFile(const char *inLogfile)
Change the file name for logging of a RooMinimizer of all MINUIT steppings through the parameter spac...
virtual bool Synchronize(std::vector< ROOT::Fit::ParameterSettings > &parameters, bool optConst, bool verbose)
Like synchronizeParameterSettings, Synchronize informs Minuit through its parameter_settings vector o...
virtual void setOptimizeConstOnFunction(RooAbsArg::ConstOpCode opcode, bool doAlsoTrackingOpt)=0
This function must be overridden in the derived class to pass on constant term optimization configura...
void BackProp(const ROOT::Fit::FitResult &results)
Put Minuit results back into RooFit objects.
void optimizeConstantTerms(bool constStatChange, bool constValChange)
void printEvalErrors() const
Print information about why evaluation failed.
void ClearPdfParamAsymErr(Int_t index)
Modify PDF parameter error by ordinal index (needed by MINUIT)
std::vector< double > getParameterValues() const
std::ofstream * _logfile
void SetPdfParamErr(Int_t index, double value)
Modify PDF parameter error by ordinal index (needed by MINUIT)
void ApplyCovarianceMatrix(TMatrixDSym &V)
Set different external covariance matrix.
std::unique_ptr< RooArgList > _initConstParamList
std::unique_ptr< RooArgList > _constParamList
RooAbsMinimizerFcn(RooArgList paramList, RooMinimizer *context, bool verbose=false)
bool synchronizeParameterSettings(std::vector< ROOT::Fit::ParameterSettings > &parameters, bool optConst, bool verbose)
Informs Minuit through its parameter_settings vector of RooFit parameter properties.
bool SetPdfParamVal(int index, double value) const
Set value of parameter i.
std::unique_ptr< RooArgList > _initFloatParamList
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
bool hasMax(const char *name=nullptr) const
Check if variable has an upper bound.
static TClass * Class()
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
bool hasMin(const char *name=nullptr) const
Check if variable has a lower bound.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:91
static void setEvalErrorLoggingMode(ErrorLoggingMode m)
Set evaluation error logging mode.
static void printEvalErrors(std::ostream &os=std::cout, Int_t maxPerNode=10000000)
Print all outstanding logged evaluation error on the given ostream.
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:22
RooMinimizer is a wrapper class around ROOT::Fit:Fitter that provides a seamless interface between th...
Definition: RooMinimizer.h:43
std::unique_ptr< RooDataSet > _logDataSet
Definition: RooMinimizer.h:161
int getPrintLevel() const
Definition: RooMinimizer.h:101
bool _loggingToDataSet
Definition: RooMinimizer.h:143
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:40
static TClass * Class()
double getError() const
Definition: RooRealVar.h:62
TClass * IsA() const override
Definition: RooRealVar.h:175
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4863
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
TClass * IsA() const override
Definition: TNamed.h:58
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
@ Minimization
Definition: RooGlobalFunc.h:61
static constexpr double eplus