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