Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MnContours.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/MnContours.h"
11#include "Minuit2/MnMinos.h"
12#include "Minuit2/MnMigrad.h"
15#include "Minuit2/FCNBase.h"
16#include "Minuit2/MnCross.h"
17#include "Minuit2/MinosError.h"
19#include "Minuit2/MnPrint.h"
20
21namespace ROOT {
22
23namespace Minuit2 {
24
25std::vector<std::pair<double, double>> MnContours::
26operator()(unsigned int px, unsigned int py, unsigned int npoints) const
27{
28 // get contour as a pair of (x,y) points passing the parameter index (px, py) and the number of requested points
29 // (>=4)
30 ContoursError cont = Contour(px, py, npoints);
31 return cont();
32}
33
34ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int npoints) const
35{
36 // calculate the contour passing the parameter index (px, py) and the number of requested points (>=4)
37 // the fcn.UP() has to be set to the required value (see Minuit document on errors)
38 assert(npoints > 3);
39 unsigned int maxcalls = 100 * (npoints + 5) * (fMinimum.UserState().VariableParameters() + 1);
40 unsigned int nfcn = 0;
41
42 MnPrint print("MnContours");
43 print.Debug("MnContours: finding ",npoints," contours points for ",px,py," at level ",fFCN.Up()," from value ",fMinimum.Fval());
44
45 std::vector<std::pair<double, double>> result;
46 result.reserve(npoints);
47 std::vector<MnUserParameterState> states;
48 // double edmmax = 0.5*0.05*fFCN.Up()*1.e-3;
49
50 // double toler = 0.05;
51 double toler = 0.1; // use same defaut value as in Minos
52
53 // get first four points running Minos separately on the two parameters
54 // and then finding the corresponding minimum in the other
55 // P1( exlow, ymin1) where ymin1 is the parameter value (y) at the minimum of f when x is fixed to exlow
56 // P2(xmin1, eylow) where xmin1 is the the parameter value (x) at the minimum of f when y is fixed to eylow
57 // P3(exup, ymin2)
58 // P4(xmin2, eyup)
60
61 double valx = fMinimum.UserState().Value(px);
62 double valy = fMinimum.UserState().Value(py);
63
64 print.Debug("Run Minos to find first 4 contour points. Current minimum is : ",valx,valy);
65
66 MinosError mnex = minos.Minos(px);
67 nfcn += mnex.NFcn();
68 if (!mnex.IsValid()) {
69 print.Error("unable to find first two points");
70 return ContoursError(px, py, result, mnex, mnex, nfcn);
71 }
72 std::pair<double, double> ex = mnex();
73
74 print.Debug("Minos error for p0: ",ex.first,ex.second);
75
76 MinosError mney = minos.Minos(py);
77 nfcn += mney.NFcn();
78 if (!mney.IsValid()) {
79 print.Error("unable to find second two points");
80 return ContoursError(px, py, result, mnex, mney, nfcn);
81 }
82 std::pair<double, double> ey = mney();
83
84 print.Debug("Minos error for p0: ",ey.first,ey.second);
85
86 // if Minos is not at limits we can use migrad to find the other corresponding point coordinate
87 MnMigrad migrad0(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1))));
88
89
90 // start from minimizing in p1 and fixing p0 to Minos value
91 migrad0.Fix(px);
92 migrad0.SetValue(px, valx + ex.first);
93 FunctionMinimum exy_lo = migrad0();
94 nfcn += exy_lo.NFcn();
95 if (!exy_lo.IsValid()) {
96 print.Error("unable to find Lower y Value for x Parameter", px);
97 return ContoursError(px, py, result, mnex, mney, nfcn);
98 }
99
100 print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_lo.UserState().Value(py),"fcn = ",exy_lo.Fval());
101
102 migrad0.SetValue(px, valx + ex.second);
103 FunctionMinimum exy_up = migrad0();
104 nfcn += exy_up.NFcn();
105 if (!exy_up.IsValid()) {
106 print.Error("unable to find Upper y Value for x Parameter", px);
107 return ContoursError(px, py, result, mnex, mney, nfcn);
108 }
109 print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_up.UserState().Value(py),"fcn = ",exy_up.Fval());
110
111
112 MnMigrad migrad1(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1))));
113 migrad1.Fix(py);
114 migrad1.SetValue(py, valy + ey.second);
115 FunctionMinimum eyx_up = migrad1();
116 nfcn += eyx_up.NFcn();
117 if (!eyx_up.IsValid()) {
118 print.Error("unable to find Upper x Value for y Parameter", py);
119 return ContoursError(px, py, result, mnex, mney, nfcn);
120 }
121 print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_up.UserState().Value(px),"fcn = ",eyx_up.Fval());
122
123 migrad1.SetValue(py, valy + ey.first);
124 FunctionMinimum eyx_lo = migrad1();
125 nfcn += eyx_lo.NFcn();
126 if (!eyx_lo.IsValid()) {
127 print.Error("unable to find Lower x Value for y Parameter", py);
128 return ContoursError(px, py, result, mnex, mney, nfcn);
129 }
130
131 print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_lo.UserState().Value(px),"fcn = ",eyx_lo.Fval());
132
133
134 double scalx = 1. / (ex.second - ex.first);
135 double scaly = 1. / (ey.second - ey.first);
136
137 result.emplace_back(valx + ex.first, exy_lo.UserState().Value(py));
138 result.emplace_back(eyx_lo.UserState().Value(px), valy + ey.first);
139 result.emplace_back(valx + ex.second, exy_up.UserState().Value(py));
140 result.emplace_back(eyx_up.UserState().Value(px), valy + ey.second);
141
143
144 print.Debug("List of first 4 found contour points", '\n', " Parameter x is", upar.Name(px), '\n', " Parameter y is", upar.Name(py),
145 '\n', result[0], '\n', result[1], '\n', result[2], '\n', result[3]);
146
147 upar.Fix(px);
148 upar.Fix(py);
149
150 std::vector<unsigned int> par(2);
151 par[0] = px;
152 par[1] = py;
153 MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy);
154
155 // find the remaining points of the contour
156 for (unsigned int i = 4; i < npoints; i++) {
157
158 // find the two neighbouring points with largest separation
159 auto idist1 = result.end() - 1;
160 auto idist2 = result.begin();
161 double dx = idist1->first - (idist2)->first;
162 double dy = idist1->second - (idist2)->second;
163 double bigdis = scalx * scalx * dx * dx + scaly * scaly * dy * dy;
164
165 for (auto ipair = result.begin(); ipair != result.end() - 1; ++ipair) {
166 double distx = ipair->first - (ipair + 1)->first;
167 double disty = ipair->second - (ipair + 1)->second;
168 double dist = scalx * scalx * distx * distx + scaly * scaly * disty * disty;
169 if (dist > bigdis) {
170 bigdis = dist;
171 idist1 = ipair;
172 idist2 = ipair + 1;
173 }
174 }
175
176 double a1 = 0.5;
177 double a2 = 0.5;
178 double sca = 1.;
179
180 L300:
181
182 if (nfcn > maxcalls) {
183 print.Error("maximum number of function calls exhausted");
184 return ContoursError(px, py, result, mnex, mney, nfcn);
185 }
186
187 print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (",
188 idist2->first,", ",idist2->second,") with weights ",a1,a2);
189 // find next point between the found 2 with max separation
190 // start from point situated at the middle (a1,a2=0.5)
191 // and direction
192 double xmidcr = a1 * idist1->first + a2 * (idist2)->first;
193 double ymidcr = a1 * idist1->second + a2 * (idist2)->second;
194 // direction is the perpendicular one
195 double xdir = (idist2)->second - idist1->second;
196 double ydir = idist1->first - (idist2)->first;
197 double scalfac = sca * std::max(std::fabs(xdir * scalx), std::fabs(ydir * scaly));
198 double xdircr = xdir / scalfac;
199 double ydircr = ydir / scalfac;
200 std::vector<double> pmid(2);
201 pmid[0] = xmidcr;
202 pmid[1] = ymidcr;
203 std::vector<double> pdir(2);
204 pdir[0] = xdircr;
205 pdir[1] = ydircr;
206
207 MnCross opt = cross(par, pmid, pdir, toler, maxcalls);
208 nfcn += opt.NFcn();
209 if (!opt.IsValid()) {
210 if(a1 > 0.5) {
211 // LM 20/10/23 : remove switch of direction and look instead closer (this is what is done in TMinuit)
212 // should we try again closer to P2 (e.g. a1=0.25, a2 = 0.75) if failing?
213 //if (sca < 0.) {
214 print.Error("unable to find point on Contour", i + 1, '\n', "found only", i, "points");
215 return ContoursError(px, py, result, mnex, mney, nfcn);
216 }
217 a1 = 0.75;
218 a2 = 0.25;
219 print.Debug("Unable to find point, try closer to p1 with weight values",a1,a2);
220 //std::cout<<"*****switch direction"<<std::endl;
221 //sca = -1.;
222 goto L300;
223 }
224 double aopt = opt.Value();
225 int pos = result.size();
226 if (idist2 == result.begin()) {
227 result.emplace_back(xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr);
228 print.Info(result.back());
229 } else {
230 print.Info(*idist2);
231 auto itr = result.insert(idist2, {xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr});
232 pos = std::distance(result.begin(),itr);
233 }
234 print.Info("Found new contour point - pos: ",pos,result[pos]);
235 }
236
237 print.Info("Number of contour points =", result.size());
238 print.Debug("List of contour points");
239 for (size_t i = 0; i < result.size(); i++)
240 print.Debug("point ",i,result[i]);
241
242 return ContoursError(px, py, result, mnex, mney, nfcn);
243}
244
245} // namespace Minuit2
246
247} // namespace ROOT
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
virtual double Up() const =0
Error definition of the function.
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
const MnUserParameterState & UserState() 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:97
double Value(unsigned int) const
void SetValue(unsigned int, double)
const FCNBase & fFCN
Definition MnContours.h:66
std::vector< std::pair< double, double > > operator()(unsigned int, unsigned int, unsigned int npoints=20) const
ask for one Contour (points only) from number of points (>=4) and parameter indices
ContoursError Contour(unsigned int, unsigned int, unsigned int npoints=20) const
ask for one Contour ContoursError (MinosErrors + points) from number of points (>=4) and parameter in...
const FunctionMinimum & fMinimum
Definition MnContours.h:67
unsigned int NFcn() const
Definition MnCross.h:95
bool IsValid() const
Definition MnCross.h:91
double Value() const
Definition MnCross.h:89
API class for minimization using Variable Metric technology ("MIGRAD"); allows for user interaction: ...
Definition MnMigrad.h:32
API class for Minos Error analysis (asymmetric errors); minimization has to be done before and Minimu...
Definition MnMinos.h:33
MinosError Minos(unsigned int, unsigned int maxcalls=0, double toler=0.1) const
ask for MinosError (Lower + Upper) can be printed via std::cout
Definition MnMinos.cxx:75
void Debug(const Ts &... args)
Definition MnPrint.h:147
void Error(const Ts &... args)
Definition MnPrint.h:129
void Info(const Ts &... args)
Definition MnPrint.h:141
API class for defining four levels of strategies: low (0), medium (1), high (2), very high (>=3); act...
Definition MnStrategy.h:27
unsigned int Strategy() const
Definition MnStrategy.h:38
class which holds the external user and/or internal Minuit representation of the parameters and error...
const char * Name(unsigned int) const
Double_t ey[n]
Definition legend1.C:17
Double_t ex[n]
Definition legend1.C:17
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...