Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "RooNaNPacker.h"
33
34#include "TClass.h"
35#include "TMatrixDSym.h"
36
37#include <fstream>
38#include <iomanip>
39
40using namespace std;
41
42RooAbsMinimizerFcn::RooAbsMinimizerFcn(RooArgList paramList, RooMinimizer *context) : _context(context)
43{
44 // Examine parameter list
45 _floatParamList.reset((RooArgList *)paramList.selectByAttrib("Constant", false));
46 if (_floatParamList->getSize() > 1) {
47 _floatParamList->sort();
48 }
49 _floatParamList->setName("floatParamList");
50
51 _constParamList.reset((RooArgList *)paramList.selectByAttrib("Constant", true));
52 if (_constParamList->getSize() > 1) {
53 _constParamList->sort();
54 }
55 _constParamList->setName("constParamList");
56
57 // Remove all non-RooRealVar parameters from list (MINUIT cannot handle them)
58 for (unsigned int i = 0; i < _floatParamList->size();) { // Note: Counting loop, since removing from collection!
59 const RooAbsArg *arg = (*_floatParamList).at(i);
61 oocoutW(_context, Minimization) << "RooAbsMinimizerFcn::RooAbsMinimizerFcn: removing parameter "
62 << arg->GetName() << " from list because it is not of type RooRealVar" << endl;
63 _floatParamList->remove(*arg);
64 } else {
65 ++i;
66 }
67 }
68
69 _nDim = _floatParamList->getSize();
70
71 // Save snapshot of initial lists
72 _initFloatParamList.reset((RooArgList *)_floatParamList->snapshot(false));
73 _initConstParamList.reset((RooArgList *)_constParamList->snapshot(false));
74}
75
77 : _context(other._context), _maxFCN(other._maxFCN), _funcOffset(other._funcOffset), _numBadNLL(other._numBadNLL),
78 _evalCounter(other._evalCounter), _nDim(other._nDim), _optConst(other._optConst),
80 _initFloatParamList((RooArgList *)other._initFloatParamList->snapshot(false)),
81 _initConstParamList((RooArgList *)other._initConstParamList->snapshot(false)), _logfile(other._logfile)
82{
83}
84
85/// Internal function to synchronize TMinimizer with current
86/// information in RooAbsReal function parameters
87bool RooAbsMinimizerFcn::synchronizeParameterSettings(std::vector<ROOT::Fit::ParameterSettings> &parameters,
88 bool optConst)
89{
90 bool constValChange(false);
91 bool constStatChange(false);
92
93 int index(0);
94
95 // Handle eventual migrations from constParamList -> floatParamList
96 for (index = 0; index < _constParamList->getSize(); index++) {
97
98 RooRealVar *par = dynamic_cast<RooRealVar *>(_constParamList->at(index));
99 if (!par)
100 continue;
101
102 RooRealVar *oldpar = dynamic_cast<RooRealVar *>(_initConstParamList->at(index));
103 if (!oldpar)
104 continue;
105
106 // Test if constness changed
107 if (!par->isConstant()) {
108
109 // Remove from constList, add to floatList
110 _constParamList->remove(*par);
111 _floatParamList->add(*par);
112 _initFloatParamList->addClone(*oldpar);
113 _initConstParamList->remove(*oldpar);
114 constStatChange = true;
115 _nDim++;
116
117 if (cfg().verbose) {
118 oocoutI(_context, Minimization)
119 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now floating." << endl;
120 }
121 }
122
123 // Test if value changed
124 if (par->getVal() != oldpar->getVal()) {
125 constValChange = true;
126 if (cfg().verbose) {
127 oocoutI(_context, Minimization)
128 << "RooAbsMinimizerFcn::synchronize: value of constant parameter " << par->GetName() << " changed from "
129 << oldpar->getVal() << " to " << par->getVal() << endl;
130 }
131 }
132 }
133
134 // Update reference list
136
137 // Synchronize MINUIT with function state
138 // Handle floatParamList
139 for (index = 0; index < _floatParamList->getSize(); index++) {
140 RooRealVar *par = dynamic_cast<RooRealVar *>(_floatParamList->at(index));
141
142 if (!par)
143 continue;
144
145 double pstep(0);
146 double pmin(0);
147 double pmax(0);
148
149 if (!par->isConstant()) {
150
151 // Verify that floating parameter is indeed of type RooRealVar
152 if (!par->IsA()->InheritsFrom(RooRealVar::Class())) {
153 oocoutW(_context, Minimization) << "RooAbsMinimizerFcn::fit: Error, non-constant parameter "
154 << par->GetName() << " is not of type RooRealVar, skipping" << endl;
155 _floatParamList->remove(*par);
156 index--;
157 _nDim--;
158 continue;
159 }
160 // make sure the parameter are in dirty state to enable
161 // a real NLL computation when the minimizer calls the function the first time
162 // (see issue #7659)
163 par->setValueDirty();
164
165 // Set the limits, if not infinite
166 if (par->hasMin())
167 pmin = par->getMin();
168 if (par->hasMax())
169 pmax = par->getMax();
170
171 // Calculate step size
172 pstep = par->getError();
173 if (pstep <= 0) {
174 // Floating parameter without error estitimate
175 if (par->hasMin() && par->hasMax()) {
176 pstep = 0.1 * (pmax - pmin);
177
178 // Trim default choice of error if within 2 sigma of limit
179 if (pmax - par->getVal() < 2 * pstep) {
180 pstep = (pmax - par->getVal()) / 2;
181 } else if (par->getVal() - pmin < 2 * pstep) {
182 pstep = (par->getVal() - pmin) / 2;
183 }
184
185 // If trimming results in zero error, restore default
186 if (pstep == 0) {
187 pstep = 0.1 * (pmax - pmin);
188 }
189
190 } else {
191 pstep = 1;
192 }
193 if (cfg().verbose) {
194 oocoutW(_context, Minimization)
195 << "RooAbsMinimizerFcn::synchronize: WARNING: no initial error estimate available for "
196 << par->GetName() << ": using " << pstep << endl;
197 }
198 }
199 } else {
200 pmin = par->getVal();
201 pmax = par->getVal();
202 }
203
204 // new parameter
205 if (index >= int(parameters.size())) {
206
207 if (par->hasMin() && par->hasMax()) {
208 parameters.emplace_back(par->GetName(), par->getVal(), pstep, pmin, pmax);
209 } else {
210 parameters.emplace_back(par->GetName(), par->getVal(), pstep);
211 if (par->hasMin())
212 parameters.back().SetLowerLimit(pmin);
213 else if (par->hasMax())
214 parameters.back().SetUpperLimit(pmax);
215 }
216
217 continue;
218 }
219
220 bool oldFixed = parameters[index].IsFixed();
221 double oldVar = parameters[index].Value();
222 double oldVerr = parameters[index].StepSize();
223 double oldVlo = parameters[index].LowerLimit();
224 double oldVhi = parameters[index].UpperLimit();
225
226 if (par->isConstant() && !oldFixed) {
227
228 // Parameter changes floating -> constant : update only value if necessary
229 if (oldVar != par->getVal()) {
230 parameters[index].SetValue(par->getVal());
231 if (cfg().verbose) {
232 oocoutI(_context, Minimization)
233 << "RooAbsMinimizerFcn::synchronize: value of parameter " << par->GetName() << " changed from "
234 << oldVar << " to " << par->getVal() << endl;
235 }
236 }
237 parameters[index].Fix();
238 constStatChange = true;
239 if (cfg().verbose) {
240 oocoutI(_context, Minimization)
241 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now fixed." << endl;
242 }
243
244 } else if (par->isConstant() && oldFixed) {
245
246 // Parameter changes constant -> constant : update only value if necessary
247 if (oldVar != par->getVal()) {
248 parameters[index].SetValue(par->getVal());
249 constValChange = true;
250
251 if (cfg().verbose) {
252 oocoutI(_context, Minimization)
253 << "RooAbsMinimizerFcn::synchronize: value of fixed parameter " << par->GetName() << " changed from "
254 << oldVar << " to " << par->getVal() << endl;
255 }
256 }
257
258 } else {
259 // Parameter changes constant -> floating
260 if (!par->isConstant() && oldFixed) {
261 parameters[index].Release();
262 constStatChange = true;
263
264 if (cfg().verbose) {
265 oocoutI(_context, Minimization)
266 << "RooAbsMinimizerFcn::synchronize: parameter " << par->GetName() << " is now floating." << endl;
267 }
268 }
269
270 // Parameter changes constant -> floating : update all if necessary
271 if (oldVar != par->getVal() || oldVlo != pmin || oldVhi != pmax || oldVerr != pstep) {
272 parameters[index].SetValue(par->getVal());
273 parameters[index].SetStepSize(pstep);
274 if (par->hasMin() && par->hasMax())
275 parameters[index].SetLimits(pmin, pmax);
276 else if (par->hasMin())
277 parameters[index].SetLowerLimit(pmin);
278 else if (par->hasMax())
279 parameters[index].SetUpperLimit(pmax);
280 }
281
282 // Inform user about changes in verbose mode
283 if (cfg().verbose) {
284 // if ierr<0, par was moved from the const list and a message was already printed
285
286 if (oldVar != par->getVal()) {
287 oocoutI(_context, Minimization)
288 << "RooAbsMinimizerFcn::synchronize: value of parameter " << par->GetName() << " changed from "
289 << oldVar << " to " << par->getVal() << endl;
290 }
291 if (oldVlo != pmin || oldVhi != pmax) {
292 oocoutI(_context, Minimization)
293 << "RooAbsMinimizerFcn::synchronize: limits of parameter " << par->GetName() << " changed from ["
294 << oldVlo << "," << oldVhi << "] to [" << pmin << "," << pmax << "]" << endl;
295 }
296
297 // If oldVerr=0, then parameter was previously fixed
298 if (oldVerr != pstep && oldVerr != 0) {
299 oocoutI(_context, Minimization)
300 << "RooAbsMinimizerFcn::synchronize: error/step size of parameter " << par->GetName()
301 << " changed from " << oldVerr << " to " << pstep << endl;
302 }
303 }
304 }
305 }
306
307 if (optConst) {
308 optimizeConstantTerms(constStatChange, constValChange);
309 }
310
311 return 0;
312}
313
314bool RooAbsMinimizerFcn::Synchronize(std::vector<ROOT::Fit::ParameterSettings> &parameters)
315{
316 return synchronizeParameterSettings(parameters, _optConst);
317}
318
319/// Modify PDF parameter error by ordinal index (needed by MINUIT)
321{
322 static_cast<RooRealVar *>(_floatParamList->at(index))->setError(value);
323}
324
325/// Modify PDF parameter error by ordinal index (needed by MINUIT)
327{
328 static_cast<RooRealVar *>(_floatParamList->at(index))->removeAsymError();
329}
330
331/// Modify PDF parameter error by ordinal index (needed by MINUIT)
332void RooAbsMinimizerFcn::SetPdfParamErr(int index, double loVal, double hiVal)
333{
334 static_cast<RooRealVar *>(_floatParamList->at(index))->setAsymError(loVal, hiVal);
335}
336
337/// Transfer MINUIT fit results back into RooFit objects.
339{
340 for (unsigned int index = 0; index < _nDim; index++) {
341 double value = results.Value(index);
343
344 // Set the parabolic error
345 double err = results.Error(index);
346 SetPdfParamErr(index, err);
347
348 double eminus = results.LowerError(index);
349 double eplus = results.UpperError(index);
350
351 if (eplus > 0 || eminus < 0) {
352 // Store the asymmetric error, if it is available
353 SetPdfParamErr(index, eminus, eplus);
354 } else {
355 // Clear the asymmetric error
357 }
358 }
359}
360
361/// Change the file name for logging of a RooMinimizer of all MINUIT steppings
362/// through the parameter space. If inLogfile is null, the current log file
363/// is closed and logging is stopped.
364bool RooAbsMinimizerFcn::SetLogFile(const char *inLogfile)
365{
366 if (_logfile) {
367 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setLogFile: closing previous log file" << endl;
368 _logfile->close();
369 delete _logfile;
370 _logfile = 0;
371 }
372 _logfile = new ofstream(inLogfile);
373 if (!_logfile->good()) {
374 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setLogFile: cannot open file " << inLogfile << endl;
375 _logfile->close();
376 delete _logfile;
377 _logfile = 0;
378 }
379
380 return false;
381}
382
383/// Apply results of given external covariance matrix. i.e. propagate its errors
384/// to all RRV parameter representations and give this matrix instead of the
385/// HESSE matrix at the next save() call
387{
388 for (unsigned int i = 0; i < _nDim; i++) {
389 // Skip fixed parameters
390 if (_floatParamList->at(i)->isConstant()) {
391 continue;
392 }
393 SetPdfParamErr(i, sqrt(V(i, i)));
394 }
395}
396
397/// Set value of parameter i.
399{
400 auto par = static_cast<RooRealVar *>(&(*_floatParamList)[index]);
401
402 if (par->getVal() != value) {
403 if (cfg().verbose)
404 cout << par->GetName() << "=" << value << ", ";
405
406 par->setVal(value);
407 return true;
408 }
409
410 return false;
411}
412
413/// Print information about why evaluation failed.
414/// Using _printEvalErrors, the number of errors printed can be steered.
415/// Negative values disable printing.
417{
418 if (cfg().printEvalErrors < 0)
419 return;
420
421 std::ostringstream msg;
422 if (cfg().doEEWall) {
423 msg << "RooAbsMinimizerFcn: Minimized function has error status." << endl
424 << "Returning maximum FCN so far (" << _maxFCN
425 << ") to force MIGRAD to back out of this region. Error log follows.\n";
426 } else {
427 msg << "RooAbsMinimizerFcn: Minimized function has error status but is ignored.\n";
428 }
429
430 msg << "Parameter values: ";
431 for (const auto par : *_floatParamList) {
432 auto var = static_cast<const RooRealVar *>(par);
433 msg << "\t" << var->GetName() << "=" << var->getVal();
434 }
435 msg << std::endl;
436
438 ooccoutW(_context, Minimization) << msg.str() << endl;
439}
440
442{
443
445
446 if (!_context->_logDataSet) {
447 const char *name = "minimizer_log_dataset";
448 _context->_logDataSet = std::make_unique<RooDataSet>(name, name, *_floatParamList);
449 }
450
452 }
453
454 _evalCounter++;
455}
456
458{
459 auto ctx = _context->makeEvalErrorContext();
460
461 if (_optConst && !flag) {
462 if (_context->getPrintLevel() > -1)
463 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization"
464 << endl;
466 _optConst = flag;
467 } else if (!_optConst && flag) {
468 if (_context->getPrintLevel() > -1)
469 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: activating const optimization"
470 << endl;
472 _optConst = flag;
473 } else if (_optConst && flag) {
474 if (_context->getPrintLevel() > -1)
475 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: const optimization already active"
476 << endl;
477 } else {
478 if (_context->getPrintLevel() > -1)
479 oocoutI(_context, Minimization) << "RooAbsMinimizerFcn::setOptimizeConst: const optimization wasn't active"
480 << endl;
481 }
482}
483
484void RooAbsMinimizerFcn::optimizeConstantTerms(bool constStatChange, bool constValChange)
485{
486 auto ctx = _context->makeEvalErrorContext();
487
488 if (constStatChange) {
489
490 oocoutI(_context, Minimization)
491 << "RooAbsMinimizerFcn::optimizeConstantTerms: set of constant parameters changed, rerunning const optimizer"
492 << endl;
494 } else if (constValChange) {
495 oocoutI(_context, Minimization)
496 << "RooAbsMinimizerFcn::optimizeConstantTerms: constant parameter values changed, rerunning const optimizer"
497 << endl;
499 }
500}
501
502std::vector<double> RooAbsMinimizerFcn::getParameterValues() const
503{
504 // TODO: make a cache for this somewhere so it doesn't have to be recreated on each call
505 std::vector<double> values;
506 values.reserve(_nDim);
507
508 for (std::size_t index = 0; index < _nDim; ++index) {
510 values.push_back(par->getVal());
511 }
512
513 return values;
514}
RooArgList * _floatParamList
Definition RooMinuit.h:85
Int_t _evalCounter
Definition RooMinuit.h:73
RooArgList * _initConstParamList
Definition RooMinuit.h:89
std::ofstream * _logfile
Definition RooMinuit.h:93
Int_t _optConst
Definition RooMinuit.h:77
RooArgList * _constParamList
Definition RooMinuit.h:88
Int_t _numBadNLL
Definition RooMinuit.h:80
RooArgList * _initFloatParamList
Definition RooMinuit.h:87
double _maxFCN
Definition RooMinuit.h:92
#define oocoutW(o, a)
#define oocoutI(o, a)
#define ooccoutW(o, a)
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
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
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:74
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:359
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition RooAbsArg.h:487
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)
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...
RooAbsMinimizerFcn(RooArgList paramList, RooMinimizer *context)
virtual bool Synchronize(std::vector< ROOT::Fit::ParameterSettings > &parameters)
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.
RooMinimizer::Config const & cfg() const
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)
bool synchronizeParameterSettings(std::vector< ROOT::Fit::ParameterSettings > &parameters, bool optConst)
Informs Minuit through its parameter_settings vector of RooFit parameter properties.
void ApplyCovarianceMatrix(TMatrixDSym &V)
Set different external covariance matrix.
std::unique_ptr< RooArgList > _initConstParamList
std::unique_ptr< RooArgList > _constParamList
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 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...
static int getPrintLevel()
Get the MINUIT internal printing level.
std::unique_ptr< RooDataSet > _logDataSet
bool _loggingToDataSet
std::unique_ptr< RooAbsReal::EvalErrorContext > makeEvalErrorContext() const
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:4874
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
TClass * IsA() const override
Definition TNamed.h:58