Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooMinimizerFcn.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 * *
8 * *
9 * Redistribution and use in source and binary forms, *
10 * with or without modification, are permitted according to the terms *
11 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
12 *****************************************************************************/
13
14#ifndef __ROOFIT_NOROOMINIMIZER
15
16//////////////////////////////////////////////////////////////////////////////
17/// \class RooMinimizerFcn
18/// RooMinimizerFcn is an interface to the ROOT::Math::IBaseFunctionMultiDim,
19/// a function that ROOT's minimisers use to carry out minimisations.
20///
21
22#include "RooMinimizerFcn.h"
23
24#include "RooAbsArg.h"
25#include "RooAbsPdf.h"
26#include "RooArgSet.h"
27#include "RooRealVar.h"
28#include "RooAbsRealLValue.h"
29#include "RooMsgService.h"
30#include "RooMinimizer.h"
31#include "RooNaNPacker.h"
32
33#include "TClass.h"
34#include "TMatrixDSym.h"
35
36#include <fstream>
37#include <iomanip>
38
39using namespace std;
40
42 bool verbose) :
43 _funct(funct), _context(context),
44 // Reset the *largest* negative log-likelihood value we have seen so far
45 _maxFCN(-std::numeric_limits<double>::infinity()), _numBadNLL(0),
46 _printEvalErrors(10),
47 _nDim(0), _logfile(0),
48 _verbose(verbose)
49{
50
51 // Examine parameter list
53 RooArgList paramList(*paramSet);
54 delete paramSet;
55
56 _floatParamList = (RooArgList*) paramList.selectByAttrib("Constant",kFALSE);
57 if (_floatParamList->getSize()>1) {
59 }
60 _floatParamList->setName("floatParamList");
61
62 _constParamList = (RooArgList*) paramList.selectByAttrib("Constant",kTRUE);
63 if (_constParamList->getSize()>1) {
65 }
66 _constParamList->setName("constParamList");
67
68 // Remove all non-RooRealVar parameters from list (MINUIT cannot handle them)
69 for (unsigned int i = 0; i < _floatParamList->size(); ) { // Note: Counting loop, since removing from collection!
70 const RooAbsArg* arg = (*_floatParamList).at(i);
71 if (!arg->IsA()->InheritsFrom(RooAbsRealLValue::Class())) {
72 oocoutW(_context,Minimization) << "RooMinimizerFcn::RooMinimizerFcn: removing parameter "
73 << arg->GetName() << " from list because it is not of type RooRealVar" << endl;
75 } else {
76 ++i;
77 }
78 }
79
81
82 // Save snapshot of initial lists
85
86}
87
88
89
90RooMinimizerFcn::RooMinimizerFcn(const RooMinimizerFcn& other) : ROOT::Math::IBaseFunctionMultiDim(other),
91 _funct(other._funct),
92 _context(other._context),
93 _maxFCN(other._maxFCN),
94 _funcOffset(other._funcOffset),
95 _recoverFromNaNStrength(other._recoverFromNaNStrength),
96 _numBadNLL(other._numBadNLL),
97 _printEvalErrors(other._printEvalErrors),
98 _evalCounter(other._evalCounter),
99 _nDim(other._nDim),
100 _logfile(other._logfile),
101 _doEvalErrorWall(other._doEvalErrorWall),
102 _verbose(other._verbose)
103{
108}
109
110
112{
113 delete _floatParamList;
114 delete _initFloatParamList;
115 delete _constParamList;
116 delete _initConstParamList;
117}
118
119
121{
122 return new RooMinimizerFcn(*this) ;
123}
124
125
126/// Internal function to synchronize TMinimizer with current
127/// information in RooAbsReal function parameters
128Bool_t RooMinimizerFcn::Synchronize(std::vector<ROOT::Fit::ParameterSettings>& parameters,
129 Bool_t optConst, Bool_t verbose)
130{
131 Bool_t constValChange(kFALSE) ;
132 Bool_t constStatChange(kFALSE) ;
133
134 Int_t index(0) ;
135
136 // Handle eventual migrations from constParamList -> floatParamList
137 for(index= 0; index < _constParamList->getSize() ; index++) {
138
139 RooRealVar *par= dynamic_cast<RooRealVar*>(_constParamList->at(index)) ;
140 if (!par) continue ;
141
142 RooRealVar *oldpar= dynamic_cast<RooRealVar*>(_initConstParamList->at(index)) ;
143 if (!oldpar) continue ;
144
145 // Test if constness changed
146 if (!par->isConstant()) {
147
148 // Remove from constList, add to floatList
149 _constParamList->remove(*par) ;
150 _floatParamList->add(*par) ;
151 _initFloatParamList->addClone(*oldpar) ;
152 _initConstParamList->remove(*oldpar) ;
153 constStatChange=kTRUE ;
154 _nDim++ ;
155
156 if (verbose) {
157 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter "
158 << par->GetName() << " is now floating." << endl ;
159 }
160 }
161
162 // Test if value changed
163 if (par->getVal()!= oldpar->getVal()) {
164 constValChange=kTRUE ;
165 if (verbose) {
166 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of constant parameter "
167 << par->GetName()
168 << " changed from " << oldpar->getVal() << " to "
169 << par->getVal() << endl ;
170 }
171 }
172
173 }
174
175 // Update reference list
177
178 // Synchronize MINUIT with function state
179 // Handle floatParamList
180 for(index= 0; index < _floatParamList->getSize(); index++) {
181 RooRealVar *par= dynamic_cast<RooRealVar*>(_floatParamList->at(index)) ;
182
183 if (!par) continue ;
184
185 Double_t pstep(0) ;
186 Double_t pmin(0) ;
187 Double_t pmax(0) ;
188
189 if(!par->isConstant()) {
190
191 // Verify that floating parameter is indeed of type RooRealVar
192 if (!par->IsA()->InheritsFrom(RooRealVar::Class())) {
193 oocoutW(_context,Minimization) << "RooMinimizerFcn::fit: Error, non-constant parameter "
194 << par->GetName()
195 << " is not of type RooRealVar, skipping" << endl ;
196 _floatParamList->remove(*par);
197 index--;
198 _nDim--;
199 continue ;
200 }
201
202 // Set the limits, if not infinite
203 if (par->hasMin() )
204 pmin = par->getMin();
205 if (par->hasMax() )
206 pmax = par->getMax();
207
208 // Calculate step size
209 pstep = par->getError();
210 if(pstep <= 0) {
211 // Floating parameter without error estitimate
212 if (par->hasMin() && par->hasMax()) {
213 pstep= 0.1*(pmax-pmin);
214
215 // Trim default choice of error if within 2 sigma of limit
216 if (pmax - par->getVal() < 2*pstep) {
217 pstep = (pmax - par->getVal())/2 ;
218 } else if (par->getVal() - pmin < 2*pstep) {
219 pstep = (par->getVal() - pmin )/2 ;
220 }
221
222 // If trimming results in zero error, restore default
223 if (pstep==0) {
224 pstep= 0.1*(pmax-pmin);
225 }
226
227 } else {
228 pstep=1 ;
229 }
230 if(verbose) {
231 oocoutW(_context,Minimization) << "RooMinimizerFcn::synchronize: WARNING: no initial error estimate available for "
232 << par->GetName() << ": using " << pstep << endl;
233 }
234 }
235 } else {
236 pmin = par->getVal() ;
237 pmax = par->getVal() ;
238 }
239
240 // new parameter
241 if (index>=Int_t(parameters.size())) {
242
243 if (par->hasMin() && par->hasMax()) {
244 parameters.push_back(ROOT::Fit::ParameterSettings(par->GetName(),
245 par->getVal(),
246 pstep,
247 pmin,pmax));
248 }
249 else {
250 parameters.push_back(ROOT::Fit::ParameterSettings(par->GetName(),
251 par->getVal(),
252 pstep));
253 if (par->hasMin() )
254 parameters.back().SetLowerLimit(pmin);
255 else if (par->hasMax() )
256 parameters.back().SetUpperLimit(pmax);
257 }
258
259 continue;
260
261 }
262
263 Bool_t oldFixed = parameters[index].IsFixed();
264 Double_t oldVar = parameters[index].Value();
265 Double_t oldVerr = parameters[index].StepSize();
266 Double_t oldVlo = parameters[index].LowerLimit();
267 Double_t oldVhi = parameters[index].UpperLimit();
268
269 if (par->isConstant() && !oldFixed) {
270
271 // Parameter changes floating -> constant : update only value if necessary
272 if (oldVar!=par->getVal()) {
273 parameters[index].SetValue(par->getVal());
274 if (verbose) {
275 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of parameter "
276 << par->GetName() << " changed from " << oldVar
277 << " to " << par->getVal() << endl ;
278 }
279 }
280 parameters[index].Fix();
281 constStatChange=kTRUE ;
282 if (verbose) {
283 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter "
284 << par->GetName() << " is now fixed." << endl ;
285 }
286
287 } else if (par->isConstant() && oldFixed) {
288
289 // Parameter changes constant -> constant : update only value if necessary
290 if (oldVar!=par->getVal()) {
291 parameters[index].SetValue(par->getVal());
292 constValChange=kTRUE ;
293
294 if (verbose) {
295 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of fixed parameter "
296 << par->GetName() << " changed from " << oldVar
297 << " to " << par->getVal() << endl ;
298 }
299 }
300
301 } else {
302 // Parameter changes constant -> floating
303 if (!par->isConstant() && oldFixed) {
304 parameters[index].Release();
305 constStatChange=kTRUE ;
306
307 if (verbose) {
308 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter "
309 << par->GetName() << " is now floating." << endl ;
310 }
311 }
312
313 // Parameter changes constant -> floating : update all if necessary
314 if (oldVar!=par->getVal() || oldVlo!=pmin || oldVhi != pmax || oldVerr!=pstep) {
315 parameters[index].SetValue(par->getVal());
316 parameters[index].SetStepSize(pstep);
317 if (par->hasMin() && par->hasMax() )
318 parameters[index].SetLimits(pmin,pmax);
319 else if (par->hasMin() )
320 parameters[index].SetLowerLimit(pmin);
321 else if (par->hasMax() )
322 parameters[index].SetUpperLimit(pmax);
323 }
324
325 // Inform user about changes in verbose mode
326 if (verbose) {
327 // if ierr<0, par was moved from the const list and a message was already printed
328
329 if (oldVar!=par->getVal()) {
330 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of parameter "
331 << par->GetName() << " changed from " << oldVar << " to "
332 << par->getVal() << endl ;
333 }
334 if (oldVlo!=pmin || oldVhi!=pmax) {
335 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: limits of parameter "
336 << par->GetName() << " changed from [" << oldVlo << "," << oldVhi
337 << "] to [" << pmin << "," << pmax << "]" << endl ;
338 }
339
340 // If oldVerr=0, then parameter was previously fixed
341 if (oldVerr!=pstep && oldVerr!=0) {
342 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: error/step size of parameter "
343 << par->GetName() << " changed from " << oldVerr << " to " << pstep << endl ;
344 }
345 }
346 }
347 }
348
349 if (optConst) {
350 if (constStatChange) {
351
353
354 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: set of constant parameters changed, rerunning const optimizer" << endl ;
356 } else if (constValChange) {
357 oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: constant parameter values changed, rerunning const optimizer" << endl ;
359 }
360
362
363 }
364
365 return 0 ;
366
367}
368
369/// Modify PDF parameter error by ordinal index (needed by MINUIT)
371{
372 static_cast<RooRealVar*>(_floatParamList->at(index))->setError(value);
373}
374
375/// Modify PDF parameter error by ordinal index (needed by MINUIT)
377{
378 static_cast<RooRealVar*>(_floatParamList->at(index))->removeAsymError();
379}
380
381/// Modify PDF parameter error by ordinal index (needed by MINUIT)
383{
384 static_cast<RooRealVar*>(_floatParamList->at(index))->setAsymError(loVal,hiVal);
385}
386
387/// Transfer MINUIT fit results back into RooFit objects.
389{
390 for (Int_t index= 0; index < _nDim; index++) {
391 Double_t value = results.Value(index);
392 SetPdfParamVal(index, value);
393
394 // Set the parabolic error
395 Double_t err = results.Error(index);
396 SetPdfParamErr(index, err);
397
398 Double_t eminus = results.LowerError(index);
399 Double_t eplus = results.UpperError(index);
400
401 if(eplus > 0 || eminus < 0) {
402 // Store the asymmetric error, if it is available
403 SetPdfParamErr(index, eminus,eplus);
404 } else {
405 // Clear the asymmetric error
406 ClearPdfParamAsymErr(index) ;
407 }
408 }
409}
410
411/// Change the file name for logging of a RooMinimizer of all MINUIT steppings
412/// through the parameter space. If inLogfile is null, the current log file
413/// is closed and logging is stopped.
414Bool_t RooMinimizerFcn::SetLogFile(const char* inLogfile)
415{
416 if (_logfile) {
417 oocoutI(_context,Minimization) << "RooMinimizerFcn::setLogFile: closing previous log file" << endl ;
418 _logfile->close() ;
419 delete _logfile ;
420 _logfile = 0 ;
421 }
422 _logfile = new ofstream(inLogfile) ;
423 if (!_logfile->good()) {
424 oocoutI(_context,Minimization) << "RooMinimizerFcn::setLogFile: cannot open file " << inLogfile << endl ;
425 _logfile->close() ;
426 delete _logfile ;
427 _logfile= 0;
428 }
429
430 return kFALSE ;
431}
432
433/// Apply results of given external covariance matrix. i.e. propagate its errors
434/// to all RRV parameter representations and give this matrix instead of the
435/// HESSE matrix at the next save() call
437{
438 for (Int_t i=0 ; i<_nDim ; i++) {
439 // Skip fixed parameters
440 if (_floatParamList->at(i)->isConstant()) {
441 continue ;
442 }
443 SetPdfParamErr(i, sqrt(V(i,i))) ;
444 }
445
446}
447
448/// Set value of parameter i.
449Bool_t RooMinimizerFcn::SetPdfParamVal(int index, double value) const
450{
451 auto par = static_cast<RooRealVar*>(&(*_floatParamList)[index]);
452
453 if (par->getVal()!=value) {
454 if (_verbose) cout << par->GetName() << "=" << value << ", " ;
455
456 par->setVal(value);
457 return kTRUE;
458 }
459
460 return kFALSE;
461}
462
463
464/// Print information about why evaluation failed.
465/// Using _printEvalErrors, the number of errors printed can be steered.
466/// Negative values disable printing.
468 if (_printEvalErrors < 0)
469 return;
470
471 std::ostringstream msg;
472 if (_doEvalErrorWall) {
473 msg << "RooMinimizerFcn: Minimized function has error status." << endl
474 << "Returning maximum FCN so far (" << _maxFCN
475 << ") to force MIGRAD to back out of this region. Error log follows.\n";
476 } else {
477 msg << "RooMinimizerFcn: Minimized function has error status but is ignored.\n";
478 }
479
480 msg << "Parameter values: " ;
481 for (const auto par : *_floatParamList) {
482 auto var = static_cast<const RooRealVar*>(par);
483 msg << "\t" << var->GetName() << "=" << var->getVal() ;
484 }
485 msg << std::endl;
486
488 ooccoutW(_context,Minimization) << msg.str() << endl;
489}
490
491
492/// Evaluate function given the parameters in `x`.
493double RooMinimizerFcn::DoEval(const double *x) const {
494
495 // Set the parameter values for this iteration
496 for (int index = 0; index < _nDim; index++) {
497 if (_logfile) (*_logfile) << x[index] << " " ;
498 SetPdfParamVal(index,x[index]);
499 }
500
501 // Calculate the function for these parameters
503 double fvalue = _funct->getVal();
505
506 if (!std::isfinite(fvalue) || RooAbsReal::numEvalErrors() > 0 || fvalue > 1e30) {
509 _numBadNLL++ ;
510
511 if (_doEvalErrorWall) {
512 const double badness = RooNaNPacker::unpackNaN(fvalue);
513 fvalue = (std::isfinite(_maxFCN) ? _maxFCN : 0.) + _recoverFromNaNStrength * badness;
514 }
515 } else {
516 if (_evalCounter > 0 && _evalCounter == _numBadNLL) {
517 // This is the first time we get a valid function value; while before, the
518 // function was always invalid. For invalid cases, we returned values > 0.
519 // Now, we offset valid values such that they are < 0.
520 _funcOffset = -fvalue;
521 }
522 fvalue += _funcOffset;
523 _maxFCN = std::max(fvalue, _maxFCN);
524 }
525
526 // Optional logging
527 if (_logfile)
528 (*_logfile) << setprecision(15) << fvalue << setprecision(4) << endl;
529 if (_verbose) {
530 cout << "\nprevFCN" << (_funct->isOffsetting()?"-offset":"") << " = " << setprecision(10)
531 << fvalue << setprecision(4) << " " ;
532 cout.flush() ;
533 }
534
535 _evalCounter++ ;
536
537 return fvalue;
538}
539
540#endif
541
double
#define oocoutW(o, a)
#define oocoutI(o, a)
#define ooccoutW(o, a)
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:92
const Bool_t kTRUE
Definition RtypesCore.h:91
double sqrt(double)
class containg 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:186
double Value(unsigned int i) const
parameter value by index
Definition FitResult.h:179
double LowerError(unsigned int i) const
lower Minos error. If Minos has not run for parameter i return the parabolic error
Class, describing value, limits and step size of the parameters Provides functionality also to set/re...
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:72
virtual void constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt=kTRUE)
Interface function signaling a request to perform constant term optimization.
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...
Bool_t isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:380
Int_t getSize() const
void sort(Bool_t reverse=false)
Sort collection using std::sort and name comparison.
RooAbsCollection * snapshot(Bool_t deepCopy=kTRUE) const
Take a snap shot of current collection contents.
virtual RooAbsArg * addClone(const RooAbsArg &var, Bool_t silent=kFALSE)
Add a clone of the specified argument to list.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsCollection * selectByAttrib(const char *name, Bool_t value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
void setName(const char *name)
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
virtual Double_t getMax(const char *name=0) const
Get maximum of currently defined range.
Bool_t hasMax(const char *name=0) const
Check if variable has an upper bound.
Bool_t hasMin(const char *name=0) const
Check if variable has a lower bound.
virtual Double_t getMin(const char *name=0) const
Get miniminum of currently defined range.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:61
virtual Bool_t isOffsetting() const
Definition RooAbsReal.h:368
static void setHideOffset(Bool_t flag)
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:91
static Int_t numEvalErrors()
Return the number of logged evaluation errors since the last clearing.
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.
static void clearEvalErrorLog()
Clear the stack of evaluation error messages.
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:21
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:70
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:29
RooMinimizerFcn is an interface to the ROOT::Math::IBaseFunctionMultiDim, a function that ROOT's mini...
RooArgList * _floatParamList
std::ofstream * _logfile
void SetPdfParamErr(Int_t index, Double_t value)
Modify PDF parameter error by ordinal index (needed by MINUIT)
RooArgList * _initFloatParamList
virtual double DoEval(const double *x) const
Evaluate function given the parameters in x.
virtual ROOT::Math::IBaseFunctionMultiDim * Clone() const
Clone a function.
Bool_t SetLogFile(const char *inLogfile)
Change the file name for logging of a RooMinimizer of all MINUIT steppings through the parameter spac...
void ApplyCovarianceMatrix(TMatrixDSym &V)
Apply results of given external covariance matrix.
RooArgList * _constParamList
Bool_t Synchronize(std::vector< ROOT::Fit::ParameterSettings > &parameters, Bool_t optConst, Bool_t verbose)
Internal function to synchronize TMinimizer with current information in RooAbsReal function parameter...
void BackProp(const ROOT::Fit::FitResult &results)
Transfer MINUIT fit results back into RooFit objects.
RooMinimizerFcn(RooAbsReal *funct, RooMinimizer *context, bool verbose=false)
void printEvalErrors() const
Print information about why evaluation failed.
RooAbsReal * _funct
const RooMinimizer * _context
void ClearPdfParamAsymErr(Int_t index)
Modify PDF parameter error by ordinal index (needed by MINUIT)
Bool_t SetPdfParamVal(int index, double value) const
Set value of parameter i.
RooArgList * _initConstParamList
double _recoverFromNaNStrength
RooMinimizer is a wrapper class around ROOT::Fit:Fitter that provides a seamless interface between th...
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:39
Double_t getError() const
Definition RooRealVar.h:60
TMatrixTSym.
Definition TMatrixTSym.h:34
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:445
Double_t x[n]
Definition legend1.C:17
Namespace for new Math classes and functions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static float unpackNaN(double val)
If val is NaN and a this NaN has been tagged as containing a payload, unpack the float from the manti...