Logo ROOT  
Reference Guide
MnPrint.cxx
Go to the documentation of this file.
1// @(#)root/minuit2:$Id$
2// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT *
7 * *
8 **********************************************************************/
9
10#include "Minuit2/MnPrint.h"
11#include "Minuit2/LAVector.h"
12#include "Minuit2/LASymMatrix.h"
20#include "Minuit2/MinosError.h"
22#include "Minuit2/MnPlot.h"
23
24#include <iomanip>
25#include <utility>
26#include <cstring>
27#include <vector>
28#include <algorithm>
29
30constexpr int PRECISION = 10;
31constexpr int WIDTH = PRECISION + 7;
32
33namespace ROOT {
34namespace Minuit2 {
35
36// we don't use a std::vector or std::array here, because we want a mix of the two;
37// a stack-allocated container with fixed capacity but dynamic size, i.e. the equivalent
38// of static_vector from the Boost Container library
39template <class T>
41public:
42 using const_pointer = const T *;
43 using const_reference = const T &;
44
45 void Push(T prefix)
46 {
47 if (fSize < fMaxSize)
48 fData[fSize] = prefix;
49 else {
50 // crop the stack when it becomes too deep as a last resort, but this should not
51 // happen, fMaxSize should be increased instead if this occurs
52 fData[fMaxSize - 1] = prefix;
53 fData[fMaxSize - 2] = "...";
54 }
55 ++fSize;
56 }
57
58 void Pop()
59 {
60 assert(fSize > 0);
61 --fSize;
62 }
63
64 const_pointer begin() const { return fData; }
65 const_pointer end() const { return fData + (fSize < fMaxSize ? fSize : fMaxSize); }
66 const_reference back() const { return *(end() - 1); }
67
68private:
69 static constexpr unsigned fMaxSize = 10; // increase as needed
71 unsigned fSize = 0;
72};
73
74// gShowPrefixStack determines how messages are printed, it acts on all threads;
75// race conditions when writing to this do not cause failures
76bool gShowPrefixStack = false;
77
78// writing to gPrefixFilter is not thread-safe, should be done only from main thread
79std::vector<std::string> gPrefixFilter;
80
81// gPrintLevel must be thread-local, because it may be manipulated by a thread to
82// temporarily turn logging on or off; Minuit2Minimizer does this, for example
83thread_local int gPrintLevel = 0;
84
85// gPrefixStack must be thread-local
87
88MnPrint::MnPrint(const char *prefix, int level) : fLevel{level}
89{
90 gPrefixStack.Push(prefix);
91}
92
94{
95 gPrefixStack.Pop();
96}
97
99{
100 gShowPrefixStack = yes;
101}
102
103void MnPrint::AddFilter(const char *filter)
104{
105 gPrefixFilter.emplace_back(filter);
106}
107
109{
110 gPrefixFilter.clear();
111}
112
114{
115 // should use std::exchange or boost::exchange
116 std::swap(gPrintLevel, level);
117 return level;
118}
119
121{
122 return gPrintLevel;
123}
124
125int MnPrint::SetLevel(int level)
126{
127 // should use std::exchange or boost::exchange
128 std::swap(fLevel, level);
129 return level;
130}
131
132int MnPrint::Level() const
133{
134 return fLevel;
135}
136
137void StreamFullPrefix(std::ostringstream &os)
138{
139 const char *prev = "";
140 for (const auto cs : gPrefixStack) {
141 // skip repeated prefixes; repetition happens when class method calls another
142 // method of the same class and both set up a MnPrint instance
143 if (std::strcmp(cs, prev) != 0)
144 os << cs << ":";
145 prev = cs;
146 }
147}
148
149void MnPrint::StreamPrefix(std::ostringstream &os)
150{
151 if (gShowPrefixStack) {
152 // show full prefix stack, useful to set sharp filters and to see what calls what
154 } else {
155 // show only the top of the prefix stack (the prefix of the innermost scope)
156 os << gPrefixStack.back();
157 }
158}
159
161{
162 // Filtering is not implemented a very efficient way to keep it simple, but the
163 // implementation ensures that the performance drop is opt-in. Only when filters are
164 // used there is a performance loss.
165
166 // The intended use case of filtering is for debugging, when highest performance
167 // does not matter. Filtering is only every attempted if the message passes the
168 // threshold level.
169
170 // Filtering is very fast when the filter is empty.
171 if (gPrefixFilter.empty())
172 return false;
173
174 std::ostringstream os;
175 os << "^";
177 std::string prefix = os.str();
178 // Filtering works like grep, the message is shown if any of the filter strings match.
179 // To only match the beginning of the prefix, use "^". For example "^MnHesse" only
180 // matches direct execution of MnHesse, but not MnHesse called by MnMigrad.
181 for (const auto &s : gPrefixFilter) {
182 if (prefix.find(s) != std::string::npos)
183 return false;
184 }
185 return true;
186}
187
188MnPrint::Oneline::Oneline(double fcn, double edm, int ncalls, int iter)
189 : fFcn(fcn), fEdm(edm), fNcalls(ncalls), fIter(iter)
190{
191}
192
194 : MnPrint::Oneline(state.Fval(), state.Edm(), state.NFcn(), iter)
195{
196}
197
198MnPrint::Oneline::Oneline(const FunctionMinimum &fmin, int iter) : MnPrint::Oneline(fmin.State(), iter) {}
199
200std::ostream &operator<<(std::ostream &os, const MnPrint::Oneline &x)
201{
202 // print iteration, function value, edm and ncalls in one single line
203 if (x.fIter >= 0)
204 os << std::setw(4) << x.fIter << " - ";
205 const int pr = os.precision(PRECISION);
206 os << "FCN = " << std::setw(WIDTH) << x.fFcn << " Edm = " << std::setw(WIDTH) << x.fEdm
207 << " NCalls = " << std::setw(6) << x.fNcalls;
208 os.precision(pr);
209 return os;
210}
211
212std::ostream &operator<<(std::ostream &os, const LAVector &vec)
213{
214 // print a vector
215 const int pr = os.precision(PRECISION);
216 const int nrow = vec.size();
217 for (int i = 0; i < nrow; i++) {
218 os << '\n';
219 os.width(WIDTH);
220 os << vec(i);
221 }
222 os.precision(pr);
223 return os;
224}
225
226std::ostream &operator<<(std::ostream &os, const LASymMatrix &matrix)
227{
228 // print a matrix
229 const int pr = os.precision(8);
230 const int n = matrix.Nrow();
231 for (int i = 0; i < n; i++) {
232 os << '\n';
233 for (int j = 0; j < n; j++) {
234 os.width(15);
235 os << matrix(i, j);
236 }
237 }
238 os.precision(pr);
239 return os;
240}
241
242std::ostream &operator<<(std::ostream &os, const MnUserParameters &par)
243{
244 // print the MnUserParameter object
245 os << "\n Pos | Name | type | Value | Error +/-";
246
247 int pr = os.precision();
248
249 const double eps2 = par.Precision().Eps2();
250 for (auto &&p : par.Parameters()) {
251 os << "\n" << std::setw(5) << p.Number() << " | " << std::setw(10) << p.Name() << " |";
252 if (p.IsConst())
253 os << " const |";
254 else if (p.IsFixed())
255 os << " fixed |";
256 else if (p.HasLimits())
257 os << " limited |";
258 else
259 os << " free |";
260 os.precision(PRECISION);
261 os.width(WIDTH);
262 os << p.Value() << " | " << std::setw(12);
263 if (p.Error() > 0) {
264 os << p.Error();
265 if (p.HasLimits()) {
266 if (std::fabs(p.Value() - p.LowerLimit()) < eps2) {
267 os << " (at lower limit)";
268 } else if (std::fabs(p.Value() - p.UpperLimit()) < eps2) {
269 os << " (at upper limit)";
270 }
271 }
272 }
273 }
274 os.precision(pr);
275
276 return os;
277}
278
279std::ostream &operator<<(std::ostream &os, const MnUserCovariance &matrix)
280{
281 // print the MnUserCovariance
282 const int pr = os.precision(6);
283
284 unsigned int n = matrix.Nrow();
285 for (unsigned int i = 0; i < n; i++) {
286 os << '\n';
287 for (unsigned int j = 0; j < n; j++) {
288 os.width(13);
289 os << matrix(i, j);
290 }
291 os << " | ";
292 double di = matrix(i, i);
293 for (unsigned int j = 0; j < n; j++) {
294 double dj = matrix(j, j);
295 os.width(13);
296 os << matrix(i, j) / std::sqrt(std::fabs(di * dj));
297 }
298 }
299 os.precision(pr);
300 return os;
301}
302
303std::ostream &operator<<(std::ostream &os, const MnGlobalCorrelationCoeff &coeff)
304{
305 // print the global correlation coefficient
306 const int pr = os.precision(6);
307 for (auto &&x : coeff.GlobalCC()) {
308 os << '\n';
309 os.width(6 + 7);
310 os << x;
311 }
312 os.precision(pr);
313 return os;
314}
315
316std::ostream &operator<<(std::ostream &os, const MnUserParameterState &state)
317{
318 // print the MnUserParameterState
319 const int pr = os.precision(PRECISION);
320 os << "\n Valid : " << (state.IsValid() ? "yes" : "NO") << "\n Function calls: " << state.NFcn()
321 << "\n Minimum value : " << state.Fval() << "\n Edm : " << state.Edm()
322 << "\n Parameters : " << state.Parameters() << "\n CovarianceStatus: " << state.CovarianceStatus()
323 << "\n Covariance and correlation matrix: ";
324 if (state.HasCovariance())
325 os << state.Covariance();
326 else
327 os << "matrix is not present or not valid";
328 if (state.HasGlobalCC())
329 os << "\n Global correlation coefficients: " << state.GlobalCC();
330
331 os.precision(pr);
332 return os;
333}
334
335std::ostream &operator<<(std::ostream &os, const FunctionMinimum &min)
336{
337 // print the FunctionMinimum
338 const int pr = os.precision(PRECISION);
339 os << "\n Valid : " << (min.IsValid() ? "yes" : "NO") << "\n Function calls: " << min.NFcn()
340 << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm()
341 << "\n Internal parameters: " << min.Parameters().Vec();
342 if (min.HasValidCovariance())
343 os << "\n Internal covariance matrix: " << min.Error().Matrix();
344 os << "\n External parameters: " << min.UserParameters();
345 // os << min.UserCovariance() << '\n';
346 // os << min.UserState().GlobalCC() << '\n';
347
348 if (!min.IsValid()) {
349 os << "\n FunctionMinimum is invalid:";
350 if (!min.State().IsValid())
351 os << "\n State is invalid";
352 if (min.IsAboveMaxEdm())
353 os << "\n Edm is above max";
354 if (min.HasReachedCallLimit())
355 os << "\n Reached call limit";
356 }
357
358 os.precision(pr);
359
360 return os;
361}
362
363std::ostream &operator<<(std::ostream &os, const MinimumState &min)
364{
365 const int pr = os.precision(PRECISION);
366 os << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm()
367 << "\n Internal parameters:" << min.Vec() << "\n Internal gradient :" << min.Gradient().Vec();
368 if (min.HasCovariance())
369 os << "\n Internal covariance matrix:" << min.Error().Matrix();
370 os.precision(pr);
371 return os;
372}
373
374std::ostream &operator<<(std::ostream &os, const MnMachinePrecision &prec)
375{
376 // print the Precision
377 int pr = os.precision(PRECISION);
378 os << "MnMachinePrecision " << prec.Eps() << '\n';
379 os.precision(pr);
380
381 return os;
382}
383
384std::ostream &operator<<(std::ostream &os, const MinosError &me)
385{
386 // print the Minos Error
387 os << "Minos # of function calls: " << me.NFcn() << '\n';
388
389 if (!me.IsValid())
390 os << "Minos Error is not valid." << '\n';
391 if (!me.LowerValid())
392 os << "lower Minos Error is not valid." << '\n';
393 if (!me.UpperValid())
394 os << "upper Minos Error is not valid." << '\n';
395 if (me.AtLowerLimit())
396 os << "Minos Error is Lower limit of Parameter " << me.Parameter() << "." << '\n';
397 if (me.AtUpperLimit())
398 os << "Minos Error is Upper limit of Parameter " << me.Parameter() << "." << '\n';
399 if (me.AtLowerMaxFcn())
400 os << "Minos number of function calls for Lower Error exhausted." << '\n';
401 if (me.AtUpperMaxFcn())
402 os << "Minos number of function calls for Upper Error exhausted." << '\n';
403 if (me.LowerNewMin()) {
404 os << "Minos found a new Minimum in negative direction." << '\n';
405 os << me.LowerState() << '\n';
406 }
407 if (me.UpperNewMin()) {
408 os << "Minos found a new Minimum in positive direction." << '\n';
409 os << me.UpperState() << '\n';
410 }
411
412 int pr = os.precision();
413
414 os << "No |"
415 << "| Name |"
416 << "| Value@min |"
417 << "| negative |"
418 << "| positive " << '\n';
419 os << std::setw(4) << me.Parameter() << std::setw(5) << "||";
420 os << std::setw(10) << me.LowerState().Name(me.Parameter()) << std::setw(3) << "||";
421 os << std::setprecision(PRECISION) << std::setw(WIDTH) << me.Min() << " ||" << std::setprecision(PRECISION)
422 << std::setw(WIDTH) << me.Lower() << " ||" << std::setw(WIDTH) << me.Upper() << '\n';
423
424 os << '\n';
425 os.precision(pr);
426
427 return os;
428}
429
430std::ostream &operator<<(std::ostream &os, const ContoursError &ce)
431{
432 // print the ContoursError
433 os << "Contours # of function calls: " << ce.NFcn() << '\n';
434 os << "MinosError in x: " << '\n';
435 os << ce.XMinosError() << '\n';
436 os << "MinosError in y: " << '\n';
437 os << ce.YMinosError() << '\n';
438 MnPlot plot;
439 plot(ce.XMin(), ce.YMin(), ce());
440 for (auto ipar = ce().begin(); ipar != ce().end(); ++ipar) {
441 os << ipar - ce().begin() << " " << (*ipar).first << " " << (*ipar).second << '\n';
442 }
443 os << '\n';
444
445 return os;
446}
447
448std::ostream &operator<<(std::ostream &os, const std::pair<double, double> &point)
449{
450 os << "\t x = " << point.first << " y = " << point.second << std::endl;
451 return os;
452}
453
454} // namespace Minuit2
455} // namespace ROOT
constexpr int PRECISION
Definition: MnPrint.cxx:30
constexpr int WIDTH
Definition: MnPrint.cxx:31
double sqrt(double)
const MinosError & YMinosError() const
Definition: ContoursError.h:62
unsigned int NFcn() const
Definition: ContoursError.h:64
const MinosError & XMinosError() const
Definition: ContoursError.h:60
const MnAlgebraicVector & Vec() const
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
const MinimumParameters & Parameters() const
const MinimumError & Error() const
const MinimumState & State() const
const MnUserParameters & UserParameters() const
Class describing a symmetric matrix of size n.
Definition: LASymMatrix.h:45
unsigned int Nrow() const
Definition: LASymMatrix.h:274
MnAlgebraicSymMatrix Matrix() const
Definition: MinimumError.h:52
const MnAlgebraicVector & Vec() const
MinimumState keeps the information (position, Gradient, 2nd deriv, etc) after one minimization step (...
Definition: MinimumState.h:27
const MinimumError & Error() const
Definition: MinimumState.h:62
const MnAlgebraicVector & Vec() const
Definition: MinimumState.h:59
const FunctionGradient & Gradient() const
Definition: MinimumState.h:63
Class holding the result of Minos (lower and upper values) for a specific parameter.
Definition: MinosError.h:25
double Upper() const
Definition: MinosError.h:63
double Min() const
Definition: MinosError.h:86
bool UpperValid() const
Definition: MinosError.h:77
unsigned int NFcn() const
Definition: MinosError.h:84
bool LowerValid() const
Definition: MinosError.h:76
unsigned int Parameter() const
Definition: MinosError.h:72
bool UpperNewMin() const
Definition: MinosError.h:83
const MnUserParameterState & UpperState() const
Definition: MinosError.h:74
bool AtUpperLimit() const
Definition: MinosError.h:79
bool AtLowerMaxFcn() const
Definition: MinosError.h:80
const MnUserParameterState & LowerState() const
Definition: MinosError.h:73
bool AtUpperMaxFcn() const
Definition: MinosError.h:81
bool LowerNewMin() const
Definition: MinosError.h:82
bool AtLowerLimit() const
Definition: MinosError.h:78
double Lower() const
Definition: MinosError.h:54
class for global correlation coefficient
const std::vector< double > & GlobalCC() const
Sets the relative floating point (double) arithmetic precision.
double Eps() const
eps returns the smallest possible number so that 1.+eps > 1.
double Eps2() const
eps2 returns 2*sqrt(eps)
MnPlot produces a text-screen graphical output of (x,y) points, e.g.
Definition: MnPlot.h:25
Oneline(double fcn, double edm, int ncalls, int iter=-1)
Definition: MnPrint.cxx:188
static void ClearFilter()
Definition: MnPrint.cxx:108
static void AddFilter(const char *prefix)
Definition: MnPrint.cxx:103
static bool Hidden()
Definition: MnPrint.cxx:160
static int GlobalLevel()
Definition: MnPrint.cxx:120
static void ShowPrefixStack(bool yes)
Definition: MnPrint.cxx:98
static int SetGlobalLevel(int level)
Definition: MnPrint.cxx:113
MnPrint(const char *prefix, int level=MnPrint::GlobalLevel())
Definition: MnPrint.cxx:88
static void StreamPrefix(std::ostringstream &os)
Definition: MnPrint.cxx:149
int SetLevel(int level)
Definition: MnPrint.cxx:125
Class containing the covariance matrix data represented as a vector of size n*(n+1)/2 Used to hide in...
class which holds the external user and/or internal Minuit representation of the parameters and error...
const MnUserParameters & Parameters() const
const MnGlobalCorrelationCoeff & GlobalCC() const
const char * Name(unsigned int) const
const MnUserCovariance & Covariance() const
API class for the user interaction with the parameters; serves as input to the minimizer as well as o...
const MnMachinePrecision & Precision() const
const std::vector< ROOT::Minuit2::MinuitParameter > & Parameters() const
access to parameters (row-wise)
void Push(T prefix)
Definition: MnPrint.cxx:45
const_reference back() const
Definition: MnPrint.cxx:66
const_pointer end() const
Definition: MnPrint.cxx:65
static constexpr unsigned fMaxSize
Definition: MnPrint.cxx:69
const_pointer begin() const
Definition: MnPrint.cxx:64
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
void swap(RDirectoryEntry &e1, RDirectoryEntry &e2) noexcept
double T(double x)
Definition: ChebyshevPol.h:34
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
std::vector< std::string > gPrefixFilter
Definition: MnPrint.cxx:79
std::ostream & operator<<(std::ostream &, const FunctionMinimum &)
Definition: MnPrint.cxx:335
thread_local PrefixStack< const char * > gPrefixStack
Definition: MnPrint.cxx:86
thread_local int gPrintLevel
Definition: MnPrint.cxx:83
bool gShowPrefixStack
Definition: MnPrint.cxx:76
void StreamFullPrefix(std::ostringstream &os)
Definition: MnPrint.cxx:137
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static constexpr double s