Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
AnalyticalGradientCalculator.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
11#include "Minuit2/FCNBase.h"
15#include "Minuit2/MnMatrix.h"
16#include "Minuit2/MnPrint.h"
17
18#include <cassert>
19
20namespace ROOT {
21namespace Minuit2 {
22
24{
25 // evaluate analytical gradient. take care of parameter transformations
26
27 std::vector<double> grad = fGradFunc.Gradient(fTransformation(par.Vec()));
28 assert(grad.size() == fTransformation.Parameters().size());
29
30 MnAlgebraicVector v(par.Vec().size());
31 for (unsigned int i = 0; i < par.Vec().size(); i++) {
32 unsigned int ext = fTransformation.ExtOfInt(i);
33 double dd = fTransformation.DInt2Ext(i, par.Vec()(i));
34 v(i) = dd * grad[ext];
35 }
36
37 MnPrint print("AnalyticalGradientCalculator");
38 print.Debug("User given gradient in Minuit2", v);
39
40 // in case we can compute Hessian do not waste re-computing G2 here
42 return FunctionGradient(v);
43
44 // compute G2 if possible
45 MnAlgebraicVector g2(par.Vec().size());
46 if (!this->G2(par, g2)) {
47 print.Error("Error computing G2");
48 return FunctionGradient(v);
49 }
50 return FunctionGradient(v,g2);
51}
52
54{
55 // needed from base class
56 return (*this)(par);
57}
58
59// G2 can be computed directly without Hessian or via the Hessian
61 return fGradFunc.HasG2() || fGradFunc.HasHessian();
62}
63
65 return fGradFunc.HasHessian();
66}
67
68
70{
71 // compute Hessian using external gradient
72 unsigned int n = par.Vec().size();
73 assert(hmat.size() == n *(n+1)/2);
74 // compute external Hessian and then transform
75 std::vector<double> extParams = fTransformation(par.Vec());
76 std::vector<double> extHessian = fGradFunc.Hessian(extParams);
77 if (extHessian.empty()) {
78 MnPrint print("AnalyticalGradientCalculator::Hessian");
79 print.Info("FCN cannot compute Hessian matrix");
80 return false;
81 }
82 unsigned int next = sqrt(extHessian.size());
83 std::vector<double> extGradient = fGradFunc.Gradient(extParams);
84 // we need now to transform the matrix from external to internal coordinates
85 for (unsigned int i = 0; i < n; i++) {
86 unsigned int iext = fTransformation.ExtOfInt(i);
87 double dxdi = fTransformation.DInt2Ext(i, par.Vec()(i));
88 for (unsigned int j = i; j < n; j++) {
89 double dxdj = fTransformation.DInt2Ext(j, par.Vec()(j));
90 unsigned int jext = fTransformation.ExtOfInt(j);
91 hmat(i, j) = dxdi * extHessian[iext*next+ jext] * dxdj;
92 if (i == j) {
93 double d2xdi2 = fTransformation.D2Int2Ext(i, par.Vec()(i));
94 if (d2xdi2 != 0.)
95 hmat(i, j) += d2xdi2 * extGradient[iext];
96 }
97 }
98 }
99 return true;
100}
101
103{
104 // compute G2 using external calculator if available; otherwise fall back to Hessian diagonal
105 const unsigned int n = par.Vec().size(); // n is size of internal parameters
106 assert(g2.size() == n);
107
108 MnPrint print("AnalyticalGradientCalculator::G2");
109
110 std::vector<double> extParams = fTransformation(par.Vec());
111 std::vector<double> extGradient = fGradFunc.Gradient(extParams);
112
113 // --- Preferred path: direct G2 from FCN ---
114 if (fGradFunc.HasG2()) {
115 std::vector<double> extG2 = fGradFunc.G2(extParams);
116 if (extG2.empty()) {
117 print.Info("FCN cannot compute the 2nd derivatives vector (G2)");
118 return false;
119 }
120 assert(extG2.size() == fTransformation.Parameters().size());
121 for (unsigned int i = 0; i < n; i++) {
122 const unsigned int iext = fTransformation.ExtOfInt(i);
123 const double dxdi = fTransformation.DInt2Ext(i, par.Vec()(i));
124 const double d2xdi2 = fTransformation.D2Int2Ext(i, par.Vec()(i));
125 g2(i) = dxdi * dxdi * extG2[iext] + d2xdi2 * extGradient[iext];
126 }
127 return true;
128 }
129
130 // --- Fallback: use Hessian diagonal if FCN provides Hessian ---
131 if (!fGradFunc.HasHessian()) {
132 print.Info("FCN cannot compute the 2nd derivatives vector (G2) or the Hessian");
133 return false;
134 }
135
136 std::vector<double> extHessian = fGradFunc.Hessian(extParams);
137 if (extHessian.empty()) {
138 print.Info("FCN cannot compute Hessian matrix (needed to derive G2)");
139 return false;
140 }
141
142 // FCNBase::Hessian is expected to return a flat nExt*nExt matrix (row-major).
143 const unsigned int nExt = static_cast<unsigned int>(std::lround(std::sqrt(static_cast<double>(extHessian.size()))));
144 if (nExt * nExt != extHessian.size()) {
145 print.Error("Unexpected Hessian size; cannot derive G2 from Hessian diagonal");
146 return false;
147 }
148 // Sanity check against transformation parameter count
149 assert(nExt == fTransformation.Parameters().size());
150
151 for (unsigned int i = 0; i < n; i++) {
152 const unsigned int iext = fTransformation.ExtOfInt(i);
153 const double diag = extHessian[iext * nExt + iext];
154 const double dxdi = fTransformation.DInt2Ext(i, par.Vec()(i));
155 const double d2xdi2 = fTransformation.D2Int2Ext(i, par.Vec()(i));
156 g2(i) = dxdi * dxdi * diag + d2xdi2 * extGradient[iext];
157 }
158 return true;
159}
160
161} // namespace Minuit2
162
163} // 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.
bool G2(const MinimumParameters &, MnAlgebraicVector &) const override
compute second derivatives (diagonal of Hessian)
FunctionGradient operator()(const MinimumParameters &) const override
bool Hessian(const MinimumParameters &, MnAlgebraicSymMatrix &) const override
compute Hessian matrix
Class describing a symmetric matrix of size n.
Definition MnMatrix.h:438
const MnAlgebraicVector & Vec() const
void Debug(const Ts &... args)
Definition MnPrint.h:135
void Error(const Ts &... args)
Definition MnPrint.h:117
void Info(const Ts &... args)
Definition MnPrint.h:129
const Int_t n
Definition legend1.C:16