npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
MinuitNeymanOSDE1DFcn.hh
Go to the documentation of this file.
1 #ifndef NPSI_MINUITNEYMANOSDE1DFCN_HH_
2 #define NPSI_MINUITNEYMANOSDE1DFCN_HH_
3 
4 /*!
5 // \file MinuitNeymanOSDE1DFcn.hh
6 //
7 // \brief Minuit function to minimize for Neyman OSDE
8 //
9 // Author: I. Volobouev
10 //
11 // March 2023
12 */
13 
14 #include <cassert>
15 
16 #include "Minuit2/FCNGradientBase.h"
18 
19 namespace npsi {
20  /**
21  // Target minimization function adapter class for running Neyman OSDE
22  // fits by Minuit2. Note that NeymanOSDE1D object is not copied,
23  // only a reference is held, with the corresponding consequences
24  // for the object lifetimes.
25  */
26  class MinuitNeymanOSDE1DFcn : public ROOT::Minuit2::FCNGradientBase
27  {
28  public:
29  inline MinuitNeymanOSDE1DFcn(
30  const npstat::NeymanOSDE1D& i_osde,
31  const unsigned nCoeffsExpected,
32  const double* shrinkages, const unsigned nShrinkages,
33  const double up=0.1)
34  : osde_(i_osde),
35  shrinkages_(shrinkages, shrinkages+nShrinkages),
36  lastGradient_(nCoeffsExpected),
37  polyStatistics_(nShrinkages),
38  lastResult_(-1.0),
39  up_(up),
40  nCoeffs_(nCoeffsExpected)
41  {
42  assert(nCoeffs_);
43  assert(nShrinkages);
44  assert(shrinkages);
45  }
46 
47  inline virtual ~MinuitNeymanOSDE1DFcn() {}
48 
49  inline const npstat::NeymanOSDE1D& getOsde() const {return osde_;}
50 
51  // Make Minuit look for a better minimum by reducing
52  // the recommended "Up" value by an order of magnitude
53  inline double Up() const {return up_;}
54 
55  // Do not waste time checking gradient calculations. They are correct.
56  inline bool CheckGradient() const {return false;}
57 
58  inline virtual double operator()(const std::vector<double>& x) const
59  {
60  calculateMemoized(x);
61  return lastResult_;
62  }
63 
64  inline std::vector<double> Gradient(const std::vector<double>& x) const
65  {
66  // Returning std::vector<double> on the stack is
67  // a pretty inefficient thing to do. However,
68  // this is how Minuit2 interface is designed.
69  calculateMemoized(x);
70  return lastGradient_;
71  }
72 
73  private:
75 
76  // Minuit2 has separate interfaces for calculating the function
77  // value and the gradient. I have yet to see a non-trivial realistic
78  // problem in which the function value can not be easily obtained
79  // along with the gradient. It would be much better to have them
80  // calculated together. We will alleviate this design problem
81  // by memoizing the argument / result pairs so that we do not
82  // have to repeat the calculation when the gradient is wanted
83  // at the same point where the function was just evaluated.
84  inline void calculateMemoized(const std::vector<double>& x) const
85  {
86  if (x != lastX_ || lastResult_ < 0.0)
87  {
88  assert(x.size() == nCoeffs_);
89  lastResult_ = osde_.chiSquare(
90  &x[0], nCoeffs_,
91  &shrinkages_[0], shrinkages_.size(),
92  &polyStatistics_[0], &lastGradient_[0]);
93  lastX_ = x;
94  }
95  }
96 
97  const npstat::NeymanOSDE1D& osde_;
98  std::vector<double> shrinkages_;
99  mutable std::vector<double> lastX_;
100  mutable std::vector<double> lastGradient_;
101  mutable std::vector<double> polyStatistics_;
102  mutable double lastResult_;
103  double up_;
104  unsigned nCoeffs_;
105  };
106 }
107 
108 #endif // MINUITNEYMANOSDE1DFCN_HH_
OSDE based on minimizing the expected ISE of the empirical comparison density.
Definition: MinuitNeymanOSDE1DFcn.hh:27
Definition: NeymanOSDE1D.hh:22
Definition: fitCompositeJohnson.hh:16