Mantid
Loading...
Searching...
No Matches
DampedGaussNewtonMinimizer.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
13
16#include "MantidAPI/IFunction.h"
17
18#include "MantidKernel/Logger.h"
19
20#include <cmath>
21
23
24namespace {
26Kernel::Logger g_log("DampedGaussNewtonMinimizer");
27} // namespace
28
29DECLARE_FUNCMINIMIZER(DampedGaussNewtonMinimizer, Damped GaussNewton)
30
31
33 declareProperty("Damping", 0.0, "The damping parameter.");
34 declareProperty("Verbose", false, "Make output more verbose.");
35}
36
38void DampedGaussNewtonMinimizer::initialize(API::ICostFunction_sptr function, size_t /*maxIterations*/) {
39 m_leastSquares = std::dynamic_pointer_cast<CostFunctions::CostFuncLeastSquares>(function);
40 if (!m_leastSquares) {
41 throw std::invalid_argument("Damped Gauss-Newton minimizer works only with least "
42 "squares. Different function was given.");
43 }
44}
45
47bool DampedGaussNewtonMinimizer::iterate(size_t /*iteration*/) {
48 const bool verbose = getProperty("Verbose");
49 const double damping = getProperty("Damping");
50
51 if (!m_leastSquares) {
52 throw std::runtime_error("Cost function isn't set up.");
53 }
54 size_t n = m_leastSquares->nParams();
55
56 if (n == 0) {
57 m_errorString = "No parameters to fit";
58 return false;
59 }
60
61 // calculate the first and second derivatives of the cost function.
62 m_leastSquares->valDerivHessian();
63
64 // copy the hessian
65 EigenMatrix H(m_leastSquares->getHessian());
66 EigenVector dd(m_leastSquares->getDeriv());
67
68 for (size_t i = 0; i < n; ++i) {
69 double tmp = H.get(i, i) + damping;
70 if (tmp == 0.0) {
71 m_errorString = "Function doesn't depend on parameter " + m_leastSquares->parameterName(i);
72 return false;
73 }
74 H.set(i, i, tmp);
75 }
76
77 if (verbose) {
78 g_log.warning() << "H:\n" << H;
79 g_log.warning() << "-----------------------------\n";
80 for (size_t j = 0; j < n; ++j) {
81 g_log.warning() << dd.get(j) << ' ';
82 }
83 g_log.warning() << '\n';
84 }
85
87 EigenVector dx(n);
88 // To find dx solve the system of linear equations H * dx == -m_der
89 dd *= -1.0;
90 try {
91 H.solve(dd, dx);
92 } catch (std::runtime_error &e) {
93 m_errorString = e.what();
94 return false;
95 }
96
97 if (verbose) {
98 for (size_t j = 0; j < n; ++j) {
99 g_log.warning() << dx.get(j) << ' ';
100 }
101 g_log.warning() << "\n\n";
102 }
103
104 // Update the parameters of the cost function.
105 for (size_t i = 0; i < n; ++i) {
106 if (!std::isfinite(dx[i])) {
107 m_errorString = "Encountered an infinite number or NaN.";
108 return false;
109 }
110 double d = m_leastSquares->getParameter(i) + dx.get(i);
111 m_leastSquares->setParameter(i, d);
112 if (verbose) {
113 g_log.warning() << i << " Parameter " << m_leastSquares->parameterName(i) << ' ' << d << '\n';
114 }
115 }
116 m_leastSquares->getFittingFunction()->applyTies();
117
118 // --- prepare for the next iteration --- //
119
120 // Try the stop condition
121 EigenVector p(n);
122 m_leastSquares->getParameters(p);
123 return dx.norm() >= m_relTol;
124}
125
128 if (!m_leastSquares) {
129 throw std::runtime_error("Cost function isn't set up.");
130 }
131 return m_leastSquares->val();
132}
133
134} // namespace Mantid::CurveFitting::FuncMinimisers
gsl_vector * tmp
#define DECLARE_FUNCMINIMIZER(classname, username)
Macro for declaring a new type of minimizers to be used with the FuncMinimizerFactory.
An interface for function minimizers.
std::string m_errorString
Error string.
A wrapper around Eigen::Matrix.
Definition EigenMatrix.h:33
A wrapper around Eigen::Vector.
Definition EigenVector.h:27
double get(const size_t i) const
Get an element.
double norm() const
Get vector norm (length)
Implements a Gauss-Newton minimization algorithm with damping for use with least squares cost functio...
std::shared_ptr< CostFunctions::CostFuncLeastSquares > m_leastSquares
Pointer to the cost function. Must be the least squares.
void initialize(API::ICostFunction_sptr function, size_t maxIterations=0) override
Initialize minimizer, i.e. pass a function to minimize.
double costFunctionVal() override
Return current value of the cost function.
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< ICostFunction > ICostFunction_sptr
define a shared pointer to a cost function