Skip to content

Commit 1caf729

Browse files
committed
[Minuit2] Improve FCNBase and FCNAdapter documentation
1 parent 1ea6400 commit 1caf729

File tree

2 files changed

+166
-118
lines changed

2 files changed

+166
-118
lines changed

math/minuit2/inc/Minuit2/FCNAdapter.h

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,77 @@
1717
#include <vector>
1818
#include <functional>
1919

20-
namespace ROOT {
21-
22-
namespace Minuit2 {
23-
24-
/**
25-
26-
27-
Wrapper class for std::function objects, adapting to FCNBase signature.
28-
29-
@author Lorenzo Moneta
30-
31-
@ingroup Minuit
32-
33-
*/
34-
20+
namespace ROOT::Minuit2 {
21+
22+
/// Adapter class to wrap user-provided functions into the FCNBase interface.
23+
///
24+
/// This class allows users to supply their function (and optionally its gradient,
25+
/// diagonal second derivatives, and Hessian) in the form of `std::function` objects.
26+
/// It adapts these functions so that they can be used transparently with the MINUIT
27+
/// minimizers via the `FCNBase` interface.
28+
///
29+
/// Typical usage:
30+
/// - Pass the function to minimize to the constructor.
31+
/// - Optionally set the gradient, G2 (second derivative diagonal), or Hessian
32+
/// functions using the provided setter methods.
33+
/// - MINUIT will then query these functions if available, or fall back to numerical
34+
/// approximations if they are not provided.
35+
///
36+
/// \ingroup Minuit
3537
class FCNAdapter : public FCNBase {
3638

3739
public:
40+
/// Construct an adapter around a user-provided function.
41+
///
42+
/// @param f Function to minimize. It must take a pointer to the parameter array
43+
/// (`double const*`) and return the function value.
44+
/// @param up Error definition parameter (defaults to 1.0).
3845
FCNAdapter(std::function<double(double const *)> f, double up = 1.) : fUp(up), fFunc(std::move(f)) {}
3946

47+
/// Indicate whether an analytic gradient has been provided.
48+
///
49+
/// @return `true` if a gradient function was set, otherwise `false`.
4050
bool HasGradient() const override { return bool(fGradFunc); }
51+
52+
/// Indicate whether analytic second derivatives (diagonal of the Hessian) are available.
53+
///
54+
/// @return `true` if a G2 function or a Hessian function has been set, otherwise `false`.
4155
bool HasG2() const override { return bool(fG2Func); }
56+
57+
/// Indicate whether an analytic Hessian has been provided.
58+
///
59+
/// @return `true` if a Hessian function was set, otherwise `false`.
4260
bool HasHessian() const override { return bool(fHessianFunc); }
4361

62+
/// Evaluate the function at the given parameter vector.
63+
///
64+
/// @param v Parameter vector.
65+
/// @return Function value at the specified parameters.
4466
double operator()(std::vector<double> const &v) const override { return fFunc(v.data()); }
4567

68+
/// Return the error definition parameter (`up`).
69+
///
70+
/// @return Current error definition value.
4671
double Up() const override { return fUp; }
4772

73+
/// Evaluate the gradient of the function at the given parameter vector.
74+
///
75+
/// @param v Parameter vector.
76+
/// @return Gradient vector (∂f/∂xᵢ) at the specified parameters.
4877
std::vector<double> Gradient(std::vector<double> const &v) const override
4978
{
5079
std::vector<double> output(v.size());
5180
fGradFunc(v.data(), output.data());
5281
return output;
5382
}
5483

55-
/// return second derivatives (diagonal of the Hessian matrix)
84+
/// Return the diagonal elements of the Hessian (second derivatives).
85+
///
86+
/// If a G2 function is set, it is used directly. If only a Hessian function
87+
/// is available, the diagonal is extracted from the full Hessian.
88+
///
89+
/// @param x Parameter vector.
90+
/// @return Vector of second derivatives (one per parameter).
5691
std::vector<double> G2(std::vector<double> const &x) const override
5792
{
5893
std::vector<double> output;
@@ -65,15 +100,21 @@ class FCNAdapter : public FCNBase {
65100
fHessian.resize(n * n);
66101
fHessianFunc(x, fHessian.data());
67102
if (!fHessian.empty()) {
68-
// get diagonal element of h
103+
// Extract diagonal elements of Hessian
69104
for (unsigned int i = 0; i < n; i++)
70105
output[i] = fHessian[i * n + i];
71106
}
72107
}
73108
return output;
74109
}
75110

76-
/// compute Hessian. Return Hessian as a std::vector of size(n*n)
111+
/// Return the full Hessian matrix.
112+
///
113+
/// If a Hessian function is available, it is used to fill the matrix.
114+
/// If the Hessian function fails, it is cleared and not used again.
115+
///
116+
/// @param x Parameter vector.
117+
/// @return Flattened Hessian matrix in row-major order.
77118
std::vector<double> Hessian(std::vector<double> const &x) const override
78119
{
79120
std::vector<double> output;
@@ -90,13 +131,33 @@ class FCNAdapter : public FCNBase {
90131
return output;
91132
}
92133

134+
/// Set the analytic gradient function.
135+
///
136+
/// @param f Gradient function of type `void(double const*, double*)`.
137+
/// The first argument is the parameter array, the second is
138+
/// the output array for the gradient values.
93139
void SetGradientFunction(std::function<void(double const *, double *)> f) { fGradFunc = std::move(f); }
140+
141+
/// Set the function providing diagonal second derivatives (G2).
142+
///
143+
/// @param f Function taking a parameter vector and returning the
144+
/// diagonal of the Hessian matrix as a vector.
94145
void SetG2Function(std::function<std::vector<double>(std::vector<double> const &)> f) { fG2Func = std::move(f); }
146+
147+
/// Set the function providing the full Hessian matrix.
148+
///
149+
/// @param f Function of type `bool(std::vector<double> const&, double*)`.
150+
/// The first argument is the parameter vector, the second is
151+
/// the output buffer (flattened matrix). The return value
152+
/// should be `true` on success, `false` on failure.
95153
void SetHessianFunction(std::function<bool(std::vector<double> const &, double *)> f)
96154
{
97155
fHessianFunc = std::move(f);
98156
}
99157

158+
/// Update the error definition parameter.
159+
///
160+
/// @param up New error definition value.
100161
void SetErrorDef(double up) override { fUp = up; }
101162

102163
private:
@@ -105,17 +166,15 @@ class FCNAdapter : public FCNBase {
105166
using G2Function = std::function<std::vector<double>(std::vector<double> const &)>;
106167
using HessianFunction = std::function<bool(std::vector<double> const &, double *)>;
107168

108-
double fUp = 1.;
109-
mutable std::vector<double> fHessian;
169+
double fUp = 1.; ///< Error definition parameter.
170+
mutable std::vector<double> fHessian; ///< Storage for intermediate Hessian values.
110171

111-
Function fFunc;
112-
GradFunction fGradFunc;
113-
G2Function fG2Func;
114-
mutable HessianFunction fHessianFunc;
172+
Function fFunc; ///< Wrapped function to minimize.
173+
GradFunction fGradFunc; ///< Optional gradient function.
174+
G2Function fG2Func; ///< Optional diagonal second-derivative function.
175+
mutable HessianFunction fHessianFunc; ///< Optional Hessian function.
115176
};
116177

117-
} // end namespace Minuit2
118-
119-
} // end namespace ROOT
178+
} // namespace ROOT::Minuit2
120179

121180
#endif // ROOT_Minuit2_FCNAdapter

math/minuit2/inc/Minuit2/FCNBase.h

Lines changed: 80 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -16,130 +16,119 @@
1616

1717
#include <vector>
1818

19-
namespace ROOT {
19+
namespace ROOT::Minuit2 {
2020

21-
namespace Minuit2 {
22-
23-
/**
24-
25-
\defgroup Minuit Minuit2 Minimization Library
26-
27-
New Object-oriented implementation of the MINUIT minimization package.
28-
More information is available at the home page of the \ref Minuit2Page "Minuit2" minimization package".
29-
30-
\ingroup Math
31-
*/
21+
/// \defgroup Minuit Minuit2 Minimization Library
22+
///
23+
/// New Object-oriented implementation of the MINUIT minimization package.
24+
/// More information is available at the home page of the \ref Minuit2Page "Minuit2" minimization package".
25+
///
26+
/// \ingroup Math
3227

3328
enum class GradientParameterSpace {
34-
External, Internal
29+
External,
30+
Internal
3531
};
3632

37-
//______________________________________________________________________________
38-
/**
39-
40-
41-
Interface (abstract class) defining the function to be minimized, which has to be implemented by the user.
42-
43-
@author Fred James and Matthias Winkler; modified by Andras Zsenei and Lorenzo Moneta
44-
45-
\ingroup Minuit
46-
47-
*/
33+
/// Interface (abstract class) defining the function to be minimized, which has to be implemented by the user.
34+
///
35+
/// \ingroup Minuit
4836

4937
class FCNBase {
5038

5139
public:
52-
5340
virtual ~FCNBase() = default;
5441

55-
/**
56-
57-
The meaning of the vector of parameters is of course defined by the user,
58-
who uses the values of those parameters to calculate their function Value.
59-
The order and the position of these parameters is strictly the one specified
60-
by the user when supplying the starting values for minimization. The starting
61-
values must be specified by the user, either via an std::vector<double> or the
62-
MnUserParameters supplied as input to the MINUIT minimizers such as
63-
VariableMetricMinimizer or MnMigrad. Later values are determined by MINUIT
64-
as it searches for the Minimum or performs whatever analysis is requested by
65-
the user.
66-
67-
@param v function parameters as defined by the user.
68-
69-
@return the Value of the function.
70-
71-
@see MnUserParameters
72-
@see VariableMetricMinimizer
73-
@see MnMigrad
74-
75-
*/
42+
/// The meaning of the vector of parameters is of course defined by the user,
43+
/// who uses the values of those parameters to calculate their function Value.
44+
/// The order and the position of these parameters is strictly the one specified
45+
/// by the user when supplying the starting values for minimization. The starting
46+
/// values must be specified by the user, either via an std::vector<double> or the
47+
/// MnUserParameters supplied as input to the MINUIT minimizers such as
48+
/// VariableMetricMinimizer or MnMigrad. Later values are determined by MINUIT
49+
/// as it searches for the Minimum or performs whatever analysis is requested by
50+
/// the user.
51+
///
52+
/// @param v function parameters as defined by the user.
53+
///
54+
/// @return the Value of the function.
55+
///
56+
/// @see MnUserParameters
57+
/// @see VariableMetricMinimizer
58+
/// @see MnMigrad
7659

7760
virtual double operator()(std::vector<double> const &v) const = 0;
7861

79-
/**
80-
81-
Error definition of the function. MINUIT defines Parameter errors as the
82-
change in Parameter Value required to change the function Value by up. Normally,
83-
for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5.
84-
If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4,
85-
as Chi2(x+n*sigma) = Chi2(x) + n*n.
86-
87-
Comment a little bit better with links!!!!!!!!!!!!!!!!!
88-
89-
*/
62+
/// Error definition of the function. MINUIT defines Parameter errors as the
63+
/// change in Parameter Value required to change the function Value by up. Normally,
64+
/// for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5.
65+
/// If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4,
66+
/// as Chi2(x+n*sigma) = Chi2(x) + n*n.
67+
///
68+
/// Comment a little bit better with links!!!!!!!!!!!!!!!!!
9069

9170
virtual double ErrorDef() const { return Up(); }
9271

93-
/**
94-
95-
Error definition of the function. MINUIT defines Parameter errors as the
96-
change in Parameter Value required to change the function Value by up. Normally,
97-
for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5.
98-
If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4,
99-
as Chi2(x+n*sigma) = Chi2(x) + n*n.
100-
101-
\todo Comment a little bit better with links!!!!!!!!!!!!!!!!! Idem for ErrorDef()
102-
103-
*/
72+
/// Error definition of the function. MINUIT defines Parameter errors as the
73+
/// change in Parameter Value required to change the function Value by up. Normally,
74+
/// for chisquared fits it is 1, and for negative log likelihood, its Value is 0.5.
75+
/// If the user wants instead the 2-sigma errors for chisquared fits, it becomes 4,
76+
/// as Chi2(x+n*sigma) = Chi2(x) + n*n.
77+
///
78+
/// \todo Comment a little bit better with links!!!!!!!!!!!!!!!!! Idem for ErrorDef()
10479

10580
virtual double Up() const = 0;
10681

107-
/**
108-
add interface to set dynamically a new error definition
109-
Re-implement this function if needed.
110-
*/
111-
virtual void SetErrorDef(double){};
82+
/// add interface to set dynamically a new error definition
83+
/// Re-implement this function if needed.
84+
virtual void SetErrorDef(double) {};
11285

11386
virtual bool HasGradient() const { return false; }
11487

115-
virtual std::vector<double> Gradient(std::vector<double> const&) const { return {}; }
116-
117-
/// In some cases, the gradient algorithm will use information from the previous step, these can be passed
118-
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
119-
/// so that these can be passed forward again as well at the call site, if necessary.
120-
virtual std::vector<double> GradientWithPrevResult(std::vector<double> const& parameters, double * /*previous_grad*/,
88+
/// Return the gradient vector of the function at the given parameter point.
89+
///
90+
/// By default, returns an empty vector (no analytic gradient provided).
91+
/// Override this method if an analytic gradient is available.
92+
///
93+
/// @param v Parameter vector.
94+
/// @return Gradient vector with respect to the parameters.
95+
virtual std::vector<double> Gradient(std::vector<double> const &) const { return {}; }
96+
97+
/// \warning Not meant to be overridden! This is a requirement for an
98+
/// internal optimization in RooFit that might go away with any refactoring.
99+
virtual std::vector<double> GradientWithPrevResult(std::vector<double> const &parameters, double * /*previous_grad*/,
121100
double * /*previous_g2*/, double * /*previous_gstep*/) const
122101
{
123102
return Gradient(parameters);
124103
};
125104

126-
virtual GradientParameterSpace gradParameterSpace() const {
127-
return GradientParameterSpace::External;
128-
};
129-
130-
/// return second derivatives (diagonal of the Hessian matrix)
131-
virtual std::vector<double> G2(std::vector<double> const&) const { return {};}
132-
133-
/// return Hessian
134-
virtual std::vector<double> Hessian(std::vector<double> const&) const { return {};}
105+
/// \warning Not meant to be overridden! This is a requirement for an
106+
/// internal optimization in RooFit that might go away with any refactoring.
107+
virtual GradientParameterSpace gradParameterSpace() const { return GradientParameterSpace::External; };
108+
109+
/// Return the diagonal elements of the Hessian (second derivatives).
110+
///
111+
/// By default, returns an empty vector. Override this method if analytic second derivatives
112+
/// (per-parameter curvature) are available.
113+
///
114+
/// @param v Parameter vector.
115+
/// @return Vector of second derivatives with respect to each parameter.
116+
virtual std::vector<double> G2(std::vector<double> const &) const { return {}; }
117+
118+
/// Return the full Hessian matrix of the function.
119+
///
120+
/// By default, returns an empty vector. Override this method if the full analytic Hessian
121+
/// (matrix of second derivatives) is available.
122+
///
123+
/// @param v Parameter vector.
124+
/// @return Flattened Hessian matrix.
125+
virtual std::vector<double> Hessian(std::vector<double> const &) const { return {}; }
135126

136127
virtual bool HasHessian() const { return false; }
137128

138129
virtual bool HasG2() const { return false; }
139130
};
140131

141-
} // namespace Minuit2
142-
143-
} // namespace ROOT
132+
} // namespace ROOT::Minuit2
144133

145134
#endif // ROOT_Minuit2_FCNBase

0 commit comments

Comments
 (0)