Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
Numerical2PGradientCalculator.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
12#include "Minuit2/MnFcn.h"
17#include "Minuit2/MnStrategy.h"
18#include "Minuit2/MnPrint.h"
19
20#ifdef _OPENMP
21#include <omp.h>
22#endif
23
24#include <cmath>
25#include <cassert>
26#include <iomanip>
27
28#include "Minuit2/MPIProcess.h"
29
30#include "./MnFcnCaller.h"
31
32namespace ROOT {
33
34namespace Minuit2 {
35
37{
38 // calculate gradient using Initial gradient calculator and from MinimumParameters object
39
41 FunctionGradient gra = gc(par);
42
43 return (*this)(par, gra);
44}
45
47operator()(const MinimumParameters &par, const FunctionGradient &Gradient) const
48{
49 // calculate numerical gradient from MinimumParameters object
50 // the algorithm takes correctly care when the gradient is approximately zero
51
52 // std::cout<<"########### Numerical2PDerivative"<<std::endl;
53 // std::cout<<"initial grd: "<<Gradient.Grad()<<std::endl;
54 // std::cout<<"position: "<<par.Vec()<<std::endl;
55 MnPrint print("Numerical2PGradientCalculator");
56
58
59 assert(par.IsValid());
60
61 double fcnmin = par.Fval();
62 // std::cout<<"fval: "<<fcnmin<<std::endl;
63
64 double eps2 = Precision().Eps2();
65 double eps = Precision().Eps();
66
67 //print.Trace("Assumed precision eps", eps, "eps2", eps2);
68
69 double dfmin = 8. * eps2 * (std::fabs(fcnmin) + fFcn.Up());
70 double vrysml = 8. * eps * eps;
71 // double vrysml = std::max(1.e-4, eps2);
72 // std::cout<<"dfmin= "<<dfmin<<std::endl;
73 // std::cout<<"vrysml= "<<vrysml<<std::endl;
74 // std::cout << " ncycle " << Ncycle() << std::endl;
75
76 unsigned int n = (par.Vec()).size();
77 unsigned int ncycle = Ncycle();
78 // MnAlgebraicVector vgrd(n), vgrd2(n), vgstp(n);
79 MnAlgebraicVector grd = Gradient.Grad();
80 MnAlgebraicVector g2 = Gradient.G2();
81 MnAlgebraicVector gstep = Gradient.Gstep();
82
83 print.Debug("Calculating gradient around function value", fcnmin, "\n\t at point", par.Vec());
84
85#ifndef _OPENMP
86
88
89 // for serial execution this can be outside the loop
90 MnAlgebraicVector x = par.Vec();
91
92 unsigned int startElementIndex = mpiproc.StartElementIndex();
93 unsigned int endElementIndex = mpiproc.EndElementIndex();
94
95 for (unsigned int i = startElementIndex; i < endElementIndex; i++) {
96
97#else
98
99 // parallelize this loop using OpenMP
100//#define N_PARALLEL_PAR 5
101#pragma omp parallel
102#pragma omp for
103 //#pragma omp for schedule (static, N_PARALLEL_PAR)
104
105 for (int i = 0; i < int(n); i++) {
106
107#endif
108
109#ifdef _OPENMP
110 // create in loop since each thread will use its own copy
111 MnAlgebraicVector x = par.Vec();
112#endif
113
114 double xtf = x(i);
115 double epspri = eps2 + std::fabs(grd(i) * eps2);
116 double stepb4 = 0.;
117 for (unsigned int j = 0; j < ncycle; j++) {
118 double optstp = std::sqrt(dfmin / (std::fabs(g2(i)) + epspri));
119 double step = std::max(optstp, std::fabs(0.1 * gstep(i)));
120 // std::cout<<"step: "<<step;
121 if (Trafo().Parameter(Trafo().ExtOfInt(i)).HasLimits()) {
122 if (step > 0.5)
123 step = 0.5;
124 }
125 double stpmax = 10. * std::fabs(gstep(i));
126 if (step > stpmax)
127 step = stpmax;
128 // std::cout<<" "<<step;
129 double stpmin = std::max(vrysml, 8. * std::fabs(eps2 * x(i)));
130 if (step < stpmin)
131 step = stpmin;
132 // std::cout<<" "<<step<<std::endl;
133 // std::cout<<"step: "<<step<<std::endl;
134 if (std::fabs((step - stepb4) / step) < StepTolerance()) {
135 // std::cout<<"(step-stepb4)/step"<<std::endl;
136 // std::cout<<"j= "<<j<<std::endl;
137 // std::cout<<"step= "<<step<<std::endl;
138 break;
139 }
140 gstep(i) = step;
141 stepb4 = step;
142 // MnAlgebraicVector pstep(n);
143 // pstep(i) = step;
144 // double fs1 = mfcnCaller(pstate + pstep);
145 // double fs2 = mfcnCaller(pstate - pstep);
146
147 x(i) = xtf + step;
148 double fs1 = mfcnCaller(x);
149 x(i) = xtf - step;
150 double fs2 = mfcnCaller(x);
151 x(i) = xtf;
152
153 double grdb4 = grd(i);
154 grd(i) = 0.5 * (fs1 - fs2) / step;
155 g2(i) = (fs1 + fs2 - 2. * fcnmin) / step / step;
156
157#ifdef _OPENMP
158#pragma omp critical
159#endif
160 {
161#ifdef _OPENMP
162 // must create thread-local MnPrint instances when printing inside threads
163 MnPrint printtl("Numerical2PGradientCalculator[OpenMP]");
164#endif
165 if (i == 0 && j == 0) {
166#ifdef _OPENMP
167 printtl.Trace([&](std::ostream &os) {
168#else
169 print.Trace([&](std::ostream &os) {
170#endif
171 os << std::setw(10) << "parameter" << std::setw(6) << "cycle" << std::setw(15) << "x" << std::setw(15)
172 << "step" << std::setw(15) << "f1" << std::setw(15) << "f2" << std::setw(15) << "grd"
173 << std::setw(15) << "g2" << std::endl;
174 });
175 }
176#ifdef _OPENMP
177 printtl.Trace([&](std::ostream &os) {
178#else
179 print.Trace([&](std::ostream &os) {
180#endif
181 const int pr = os.precision(13);
182 const int iext = Trafo().ExtOfInt(i);
183 os << std::setw(10) << Trafo().Name(iext) << std::setw(5) << j << " " << x(i) << " " << step << " "
184 << fs1 << " " << fs2 << " " << grd(i) << " " << g2(i) << std::endl;
185 os.precision(pr);
186 });
187 }
188
189 if (std::fabs(grdb4 - grd(i)) / (std::fabs(grd(i)) + dfmin / step) < GradTolerance()) {
190 // std::cout<<"j= "<<j<<std::endl;
191 // std::cout<<"step= "<<step<<std::endl;
192 // std::cout<<"fs1, fs2: "<<fs1<<" "<<fs2<<std::endl;
193 // std::cout<<"fs1-fs2: "<<fs1-fs2<<std::endl;
194 break;
195 }
196 }
197
198 // vgrd(i) = grd;
199 // vgrd2(i) = g2;
200 // vgstp(i) = gstep;
201 }
202
203#ifndef _OPENMP
204 mpiproc.SyncVector(grd);
205 mpiproc.SyncVector(g2);
206 mpiproc.SyncVector(gstep);
207#endif
208
209 // print after parallel processing to avoid synchronization issues
210 print.Debug([&](std::ostream &os) {
211 const int pr = os.precision(13);
212 os << std::endl;
213 os << std::setw(14) << "Parameter" << std::setw(14) << "Gradient" << std::setw(14) << "g2 " << std::setw(14)
214 << "step" << std::endl;
215 for (int i = 0; i < int(n); i++) {
216 const int iext = Trafo().ExtOfInt(i);
217 os << std::setw(14) << Trafo().Name(iext) << " " << grd(i) << " " << g2(i) << " " << gstep(i) << std::endl;
218 }
219 os.precision(pr);
220 });
221
222 return FunctionGradient(grd, g2, gstep);
223}
224
226{
227 // return global precision (set in transformation)
228 return fTransformation.Precision();
229}
230
232{
233 // return number of cycles for gradient calculation (set in strategy object)
234 return Strategy().GradientNCycles();
235}
236
238{
239 // return gradient step tolerance (set in strategy object)
240 return Strategy().GradientStepTolerance();
241}
242
244{
245 // return gradient tolerance (set in strategy object)
246 return Strategy().GradientTolerance();
247}
248
249} // namespace Minuit2
250
251} // namespace ROOT
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
Class to calculate an initial estimate of the gradient.
const MnAlgebraicVector & Vec() const
Sets the relative floating point (double) arithmetic precision.
void Debug(const Ts &... args)
Definition MnPrint.h:133
void Trace(const Ts &... args)
Definition MnPrint.h:139
FunctionGradient operator()(const MinimumParameters &) const override
CPyCppyy::Parameter Parameter
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...