Mantid
Loading...
Searching...
No Matches
CostFuncLeastSquares.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//----------------------------------------------------------------------
16#include "MantidKernel/Logger.h"
18
19#include <sstream>
20
22namespace {
24Kernel::Logger g_log("CostFuncLeastSquares");
25} // namespace
26
27DECLARE_COSTFUNCTION(CostFuncLeastSquares, Least squares)
28
29
40 m_function->function(*domain, *values);
41 size_t ny = values->size();
42
43 double retVal = 0.0;
44
45 std::vector<double> weights = getFitWeights(values);
46
47 for (size_t i = 0; i < ny; i++) {
48 double val = (values->getCalculated(i) - values->getFitData(i)) * weights[i];
49 retVal += val * val;
50 }
51
53 m_value += m_factor * retVal;
54}
55
66 API::FunctionValues_sptr values, bool evalDeriv, bool evalHessian) const {
67 UNUSED_ARG(evalDeriv);
68 function->function(*domain, *values);
69 size_t np = function->nParams(); // number of parameters
70 size_t ny = values->size(); // number of data points
71 Jacobian jacobian(ny, np);
72 function->functionDeriv(*domain, jacobian);
73
74 size_t iActiveP = 0;
75 double fVal = 0.0;
76 std::vector<double> weights = getFitWeights(values);
77
78 for (size_t ip = 0; ip < np; ++ip) {
79 if (!function->isActive(ip))
80 continue;
81
82 double d = 0.0;
83 for (size_t i = 0; i < ny; ++i) {
84 double calc = values->getCalculated(i);
85 double obs = values->getFitData(i);
86 double w = weights[i];
87 double y = (calc - obs) * w;
88 d += y * jacobian.get(i, ip) * w;
89 if (iActiveP == 0) {
90 fVal += y * y;
91 }
92 }
93 PARALLEL_CRITICAL(der_set) {
94 double der = m_der.get(iActiveP);
95 m_der.set(iActiveP, der + d);
96 }
97 ++iActiveP;
98
99 if (iActiveP >= m_der.size())
100 break;
101 }
102
104 m_value += 0.5 * fVal;
105
106 if (!evalHessian)
107 return;
108
109 size_t i1 = 0; // active parameter index
110 for (size_t i = 0; i < np; ++i) // over parameters
111 {
112 if (!function->isActive(i))
113 continue;
114 size_t i2 = 0; // active parameter index
115 for (size_t j = 0; j <= i; ++j) // over ~ half of parameters
116 {
117 if (!function->isActive(j))
118 continue;
119 double d = 0.0;
120 for (size_t k = 0; k < ny; ++k) // over fitting data
121 {
122 double w = weights[k];
123 d += jacobian.get(k, i) * jacobian.get(k, j) * w * w;
124 }
125 PARALLEL_CRITICAL(hessian_set) {
126 double h = m_hessian.get(i1, i2);
127 m_hessian.set(i1, i2, h + d);
128 if (i1 != i2) {
129 m_hessian.set(i2, i1, h + d);
130 }
131 }
132 ++i2;
133
134 if (i2 >= m_hessian.size2())
135 break;
136 }
137 ++i1;
138
139 if (i1 >= m_hessian.size1())
140 break;
141 }
142}
143
145 std::vector<double> weights(values->size());
146 for (size_t i = 0; i < weights.size(); ++i) {
147 weights[i] = values->getFitWeight(i);
148 }
149
150 return weights;
151}
152
159 UNUSED_ARG(epsrel);
160
161 if (m_hessian.isEmpty()) {
163 }
164
165 if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) {
166 std::ostringstream osHess;
167 osHess << "== Hessian (H) ==\n";
168 osHess << std::left << std::fixed;
169 for (size_t i = 0; i < m_hessian.size1(); ++i) {
170 for (size_t j = 0; j < m_hessian.size2(); ++j) {
171 osHess << std::setw(10);
172 osHess << m_hessian.get(i, j) << " ";
173 }
174 osHess << "\n";
175 }
176 g_log.debug() << osHess.str();
177 }
178
179 covar = m_hessian;
180 covar.invert();
181 if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) {
182 std::ostringstream osCovar;
183 osCovar << "== Covariance matrix (H^-1) ==\n";
184 osCovar << std::left << std::fixed;
185 for (size_t i = 0; i < covar.size1(); ++i) {
186 for (size_t j = 0; j < covar.size2(); ++j) {
187 osCovar << std::setw(10);
188 osCovar << covar.get(i, j) << " ";
189 }
190 osCovar << "\n";
191 }
192 g_log.debug() << osCovar.str();
193 }
194}
195
196} // namespace Mantid::CurveFitting::CostFunctions
#define DECLARE_COSTFUNCTION(classname, username)
Macro for declaring a new type of cost functions to be used with the CostFunctionFactory.
Definition: ICostFunction.h:66
#define PARALLEL_CRITICAL(name)
#define PARALLEL_ATOMIC
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
Represents the Jacobian in IFitFunction::functionDeriv.
Definition: Jacobian.h:22
virtual double get(size_t iY, size_t iP)=0
Get the value to a Jacobian matrix element.
A semi-abstract class for a cost function for fitting functions.
virtual double valDerivHessian(bool evalDeriv=true, bool evalHessian=true) const
Calculate the value, the first and the second derivatives of the cost function.
API::IFunction_sptr m_function
Shared pointer to the fitting function.
virtual double val() const override
Calculate value of cost function.
void calActiveCovarianceMatrix(EigenMatrix &covar, double epsrel=1e-8) override
Calculates covariance matrix for fitting function's active parameters.
void addVal(API::FunctionDomain_sptr domain, API::FunctionValues_sptr values) const override
Add a contribution to the cost function value from the fitting function evaluated on a particular dom...
void addValDerivHessian(API::IFunction_sptr function, API::FunctionDomain_sptr domain, API::FunctionValues_sptr values, bool evalDeriv=true, bool evalHessian=true) const override
Update the cost function, derivatives and hessian by adding values calculated on a domain.
virtual std::vector< double > getFitWeights(API::FunctionValues_sptr values) const
Get mapped weights from FunctionValues.
A wrapper around Eigen::Matrix.
Definition: EigenMatrix.h:33
bool isEmpty() const
Is matrix empty.
void set(size_t i, size_t j, double value)
Set an element.
double get(size_t i, size_t j) const
Get an element.
size_t size1() const
First size of the matrix.
void invert()
Invert this matrix.
size_t size2() const
Second size of the matrix.
void set(const size_t i, const double value)
Set an element.
double get(const size_t i) const
Get an element.
size_t size() const
Size of the vector.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
bool is(int level) const
Returns true if at least the given log level is set.
Definition: Logger.cpp:146
std::shared_ptr< FunctionValues > FunctionValues_sptr
typedef for a shared pointer
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
std::shared_ptr< FunctionDomain > FunctionDomain_sptr
typedef for a shared pointer