npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
NeymanOSDE1DConvergence.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_NEYMANOSDE1DCONVERGENCE_HH_
2 #define NPSTAT_NEYMANOSDE1DCONVERGENCE_HH_
3 
4 /*!
5 // \file NeymanOSDE1DConvergence.hh
6 //
7 // \brief Classes for establishing convergence of the Neyman OSDE
8 // optimization algorithms
9 //
10 // Author: I. Volobouev
11 //
12 // March 2023
13 */
14 
15 #include <vector>
16 #include <cmath>
17 #include <cassert>
18 
19 #include "npstat/nm/Matrix.hh"
20 
21 namespace npstat {
22  // Convergence is established when either all
23  // components of the gradient are small in
24  // magnitude (useL2Distance parameter is false)
25  // or the norm of the gradient is small
26  // (useL2Distance parameter is true).
27  //
29  {
30  public:
32  const double i_eps, const bool i_useL2Distance = false)
33  : eps_(i_eps), useL2Distance_(i_useL2Distance)
34  {
35  assert(eps_ >= 0.0);
36  }
37 
38  inline bool converged(const unsigned /* iterationNumber */,
39  const double /* prevChisq */,
40  const std::vector<double>& /* prevGradient */,
41  const std::vector<double>& /* lastStep */,
42  const double /* currentChisq */,
43  const std::vector<double>& currentGradient,
44  const Matrix<double>& /* hessian */) const
45  {
46  const unsigned sz = currentGradient.size();
47  if (useL2Distance_)
48  {
49  long double sum = 0.0L;
50  for (unsigned i=0; i<sz; ++i)
51  sum += currentGradient[i]*currentGradient[i];
52  return sum <= sz*eps_*eps_;
53  }
54  else
55  {
56  for (unsigned i=0; i<sz; ++i)
57  if (std::abs(currentGradient[i]) > eps_)
58  return false;
59  return true;
60  }
61  }
62 
63  private:
64  double eps_;
65  bool useL2Distance_;
66  };
67 
68  // Convergence is established if either the
69  // convergence conditions are satisfied for the
70  // argument of the other convergence calculator
71  // or the Hessian becomes positive-definite.
72  //
73  // Intended for automatic switching between
74  // gradient descent and Newton's method.
75  //
76  template<class OtherConvergenceCalc>
78  {
79  public:
80  inline explicit HessianNeymanOSDE1DConvergenceCalc(
81  const OtherConvergenceCalc& gcalc)
82  : gcalc_(gcalc), gcalcConverged_(false) {}
83 
84  inline bool otherCalcConverged() const {return gcalcConverged_;}
85 
86  inline bool converged(const unsigned iterationNumber,
87  const double prevChisq,
88  const std::vector<double>& prevGradient,
89  const std::vector<double>& lastStep,
90  const double currentChisq,
91  const std::vector<double>& currentGradient,
92  const Matrix<double>& hessian) const
93  {
94  gcalcConverged_ = gcalc_.converged(iterationNumber, prevChisq,
95  prevGradient, lastStep,
96  currentChisq, currentGradient,
97  hessian);
98  if (gcalcConverged_)
99  return true;
100 
101  assert(hessian.isSquare());
102  const unsigned sz = hessian.nRows();
103  std::vector<double> eigenvalues(sz);
104  hessian.symEigen(&eigenvalues[0], sz);
105  for (unsigned i=0; i<sz; ++i)
106  if (eigenvalues[i] <= 0.0)
107  return false;
108  return true;
109  }
110 
111  private:
112  OtherConvergenceCalc gcalc_;
113  mutable bool gcalcConverged_;
114  };
115 }
116 
117 #endif // NPSTAT_NEYMANOSDE1DCONVERGENCE_HH_
Template matrix class.
Definition: NeymanOSDE1DConvergence.hh:29
Definition: NeymanOSDE1DConvergence.hh:78
unsigned nRows() const
Definition: Matrix.hh:155
void symEigen(Numeric *eigenvalues, unsigned lenEigenvalues, Matrix *eigenvectors=0, EigenMethod m=EIGEN_SIMPLE) const
Definition: AbsArrayProjector.hh:14