QMCPACK
NonlinearFit.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
8 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #ifndef NONLINEAR_FIT_H
15 #define NONLINEAR_FIT_H
16 
17 #include "Blitz.h"
18 #include "blitz/tinyvec.h"
19 #include "blitz/array.h"
20 #include "MatrixOps.h"
21 
22 // Template class for fitting a function with M nonlinear parameters.
23 template<int M, typename ModelType>
25 {
26 private:
27  ModelType Model;
31  double Chi2(const Array<double, 1>& x,
32  const Array<double, 1>& y,
33  const Array<double, 1>& sigma,
34  TinyVector<double, M> params);
35  void CalcAlphaBeta(const Array<double, 1>& x,
36  const Array<double, 1>& y,
37  const Array<double, 1>& sigma,
38  TinyVector<double, M> params);
39  void Solve();
40 
41 public:
42  void Fit(const Array<double, 1>& x,
43  const Array<double, 1>& y,
44  const Array<double, 1>& sigma,
45  TinyVector<double, M>& params);
46 
47  inline Array<double, 2>& GetCovariance() { return AlphaInv; }
48 
49  NonlinearFitClass(ModelType model) : Model(model) { AlphaInv.resize(M, M); };
50 };
51 
52 
53 template<int M, typename ModelType>
55  const Array<double, 1>& y,
56  const Array<double, 1>& sigma,
57  TinyVector<double, M> params)
58 {
59  int N = x.size();
60  assert(y.size() == N);
61  assert(sigma.size() == N);
62  Model.SetParams(params);
63 
64  double chi2 = 0;
65  for (int i = 0; i < N; i++)
66  {
67  double val = Model(x(i));
68  // std::cerr << "val = " << val << std::endl;
69  // std::cerr << "yi = " << y(i) << std::endl;
70  // std::cerr << "sigma = " << sigma(i) << std::endl;
71  chi2 += (val - y(i)) * (val - y(i)) / (sigma(i) * sigma(i));
72  }
73  return chi2;
74 }
75 
76 template<int M, typename ModelType>
78  const Array<double, 1>& y,
79  const Array<double, 1>& sigma,
80  TinyVector<double, M> params)
81 {
82  Model.SetParams(params);
83  int N = x.size();
84  assert(y.size() == N);
85  assert(sigma.size() == N);
86 
87  for (int k = 0; k < M; k++)
88  {
89  Beta[k] = 0.0;
90  for (int l = 0; l < M; l++)
91  Alpha(k, l) = 0.0;
92  }
93 
94  for (int i = 0; i < N; i++)
95  {
96  double val = Model(x(i));
97  TinyVector<double, M> grad = Model.Grad(x(i));
98  for (int k = 0; k < M; k++)
99  Beta[k] += grad[k] * (y(i) - val) / (sigma(i) * sigma(i));
100  }
101  for (int i = 0; i < N; i++)
102  {
103  double val = Model(x(i));
104  TinyVector<double, M> grad = Model.Grad(x(i));
105  for (int k = 0; k < M; k++)
106  for (int l = 0; l < M; l++)
107  Alpha(k, l) += grad[k] * grad[l] / (sigma(i) * sigma(i));
108  }
109  // std::cerr << "Alpha = " << Alpha << std::endl;
110 }
111 
112 
113 template<int M, typename ModelType>
115 {
116  for (int i = 0; i < M; i++)
117  {
118  dParams[i] = 0.0;
119  for (int j = 0; j < M; j++)
120  AlphaInv(i, j) = Alpha(i, j);
121  }
122 
123  GJInverse(AlphaInv);
125  id = 0.0;
126  for (int i = 0; i < M; i++)
127  for (int j = 0; j < M; j++)
128  for (int k = 0; k < M; k++)
129  id(i, j) += AlphaInv(i, k) * Alpha(k, j);
130 
131  for (int i = 0; i < M; i++)
132  for (int j = 0; j < M; j++)
133  dParams[i] += AlphaInv(i, j) * Beta(j);
134 
135  // Do simple Gaussian elimination
136  // double dInv = 1.0/Alpha(0,0);
137  // for (int col=0; col<M; col++)
138  // Alpha(0,col) *= dInv;
139  // Beta(0) *= dInv;
140  // for (int row=1; row<M; row++) {
141  // for (int col=0; col<row; col++) {
142  // Beta(row) -= Alpha(row,col)*Beta(col);
143  // for (int k=0;
144  // double diag = Alpha(row,row);
145  // double diagInv = 1.0/diag;
146  // for (int col=0; col<M; col++)
147  // Beta(row) *= diagInv;
148  // for (int col=row+1; col<
149 }
150 
151 
152 template<int M, typename ModelType>
154  const Array<double, 1>& y,
155  const Array<double, 1>& sigma,
156  TinyVector<double, M>& params)
157 {
158  double chiNow = Chi2(x, y, sigma, params);
159  double lambda = 0.01;
160 
161  bool done = false;
162  int iter = 1;
163  int numSmallDecrease = 0;
164  while (!done)
165  {
166  // std::cerr << "Iteration " << iter << ": Chi2 = " << chiNow << std::endl;
167  // std::cerr << "params = " << params << std::endl;
168  // std::cerr << "lambda = " << lambda << std::endl;
169 
170  CalcAlphaBeta(x, y, sigma, params);
171  for (int i = 0; i < M; i++)
172  Alpha(i, i) *= (1.0 + lambda);
173  Solve();
174  // done = true;
175  // for (int i=0; i<M; i++)
176  // if (std::abs(Beta[i]) > 1.0e-6)
177  // done = false;
178  if (!done)
179  {
180  double chiNew = Chi2(x, y, sigma, params + dParams);
181  if (chiNew <= chiNow)
182  {
183  lambda *= 0.5;
184  params = params + dParams;
185  if ((chiNow - chiNew) < 0.001)
186  numSmallDecrease++;
187  if (numSmallDecrease > 4)
188  done = true;
189  chiNow = chiNew;
190  }
191  else
192  {
193  lambda *= 2.0;
194  }
195  }
196  iter++;
197  }
198  CalcAlphaBeta(x, y, sigma, params);
199  for (int i = 0; i < M; i++)
200  for (int j = 0; j < M; j++)
201  AlphaInv(i, j) = Alpha(i, j);
202  GJInverse(AlphaInv);
203  // std::cerr << "Covariace matrix:\n";
204  // for (int i=0; i<AlphaInv.rows(); i++) {
205  // for (int j=0; j<AlphaInv.cols(); j++)
206  // fprintf (stderr, "%12.4e ", AlphaInv(i,j));
207  // fprintf (stderr, "\n");
208  // }
209  Model.SetParams(params);
210  // std::cerr << "Chi2 = " << chiNow << std::endl;
211 }
212 
213 #endif
double GJInverse(Array< double, 2 > &A)
void CalcAlphaBeta(const Array< double, 1 > &x, const Array< double, 1 > &y, const Array< double, 1 > &sigma, TinyVector< double, M > params)
Definition: NonlinearFit.h:77
TinyVector< double, M > Params
Definition: NonlinearFit.h:28
double Chi2(const Array< double, 1 > &x, const Array< double, 1 > &y, const Array< double, 1 > &sigma, TinyVector< double, M > params)
Definition: NonlinearFit.h:54
TinyVector< double, M > Beta
Definition: NonlinearFit.h:28
void resize(const std::array< SIZET, D > &dims)
Resize the container.
Definition: OhmmsArray.h:65
TinyVector< double, M > dParams
Definition: NonlinearFit.h:28
TinyMatrix< double, M, M > Alpha
Definition: NonlinearFit.h:29
size_t size() const
Definition: OhmmsArray.h:57
NonlinearFitClass(ModelType model)
Definition: NonlinearFit.h:49
constexpr double done
Definition: BLAS.hpp:48
Array< double, 2 > & GetCovariance()
Definition: NonlinearFit.h:47
void Fit(const Array< double, 1 > &x, const Array< double, 1 > &y, const Array< double, 1 > &sigma, TinyVector< double, M > &params)
Definition: NonlinearFit.h:153
Array< double, 2 > AlphaInv
Definition: NonlinearFit.h:30