TBCI Numerical high perf. C++ Library 2.8.0
LM_fit.h
Go to the documentation of this file.
1
4/***************************************************************************
5 LM_fit.h - Levenbaerg-Marquardt non-linear data fit
6 -------------------
7 begin : Wed Dec 15 1999
8 copyright : (C) 1999 by AMB
9 email : bilgic@hft.e-technik.uni-dortmund.de
10 ***************************************************************************/
11
12/***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21
22#ifndef TBCI_LM_FIT_H
23#define TBCI_LM_FIT_H
24
25#include "tbci/basics.h"
26#include "tbci/vector.h"
27#include "tbci/matrix.h"
28#include "tbci/constants.h"
29#include "tbci/solver/gauss_jordan.h"
30//#include "list.h"
31
32#ifdef HAVE_SIGNALS
33# include <signal.h>
34#endif
35/*
36#include <cstdlib>
37#include <cmath>
38#include <iostream>
39#include <iomanip>
40*/
41
42
44
45#ifdef PRAGMA_I
46# pragma interface "LM_fit.h"
47#endif
48
49#define DELTAX 1e-30
50
52
53#define DELTA(i,j) ((i==j)?1:0)
54
55/*
56inline int delta (int i, int j)
57{
58 return ((i==j) ? 1 : 0);
59}
60 */
61
62INST(template <typename T> class Vector friend \
63 int Basis_Trafo (long int, long int, Vector<T>&);)
64
65template <typename T>
66int Basis_Trafo (long int value, long int basis, Vector<T>& index)
67/* transforms the integer 'value' into the basis 'basis';
68 index contain the resulting digits with lowest significant first */
69{
70 int n = index.size();
71 int i = 0;
72
73 index = (T)0;
74 if (value == 0) return 1; //special zero treatment
75 if (n < (int)CSTD__ ceil (MATH__ sqrt(2*MATH__ log((double)value) / MATH__ log((double)basis))) || basis <= 1) return 0;
76 while (value > 0)
77 {
78 index(i) = value%basis;
79 value /= basis;
80 i++;
81 }
82 return 1;
83}
84
85
86#define CON2 2.0
87#define CON SQRT2
88#define BIG 1.0e30
89#define NTAB 10
90#define SAFE 2.0
91
92INST(template <typename T> class Vector friend \
93 T Partial_Del (T (*func)(const Vector<T>&, const Vector<T>&), \
94 const Vector<T>&, const Vector<T>&, \
95 int, T, T&);)
96template <typename T>
97T Partial_Del (T (*func)(const Vector<T>&, const Vector<T>&),
98 const Vector<T>& x, const Vector<T>& p,
99 int mu, T h, T& err)
100 // calculate partial derivative of func with respect to mu
101 // Acc. to Num. recipes, ch. 5.7
102{
103 //static T maxarg1 ALIGN(MIN_ALIGN), maxarg2 ALIGN(MIN_ALIGN);
104 T errt ALIGN(MIN_ALIGN), fac, hh, ans = (T)0;
105 int xlen = x.size();
109#ifdef FOURTHORDER
110 Vector<T> buf_plus2(xlen);
111 Vector<T> buf_minus2(xlen);
112#endif
113 if (mu >= xlen)
114 STD__ cerr << "\n error: partial_del: derivate variable index out of range \n";
115 hh = h ;
116 buf_plus = x; buf_minus = x; buf_plus(mu) += hh; buf_minus(mu) -= hh;
117#ifdef FOURTHORDER
118 buf_plus2 = x; buf_minus2 = x; buf_plus2(mu) += hh*2; buf_minus2 -= hh*2;
119 a(0,0) = (-(*func)(buf_plus2, p) + 8.0*(*func)(buf_plus, p)
120 - 8.0*(*func)(buf_minus, p) + (*func)(buf_minus2, p)) / (hh*12.0);
121#else
122 a(0,0) = ((*func)(buf_plus, p) - (*func)(buf_minus, p)) / (2.0*hh);
123#endif
124 err = BIG;
125 for (int i = 1; i < NTAB; i++) {
126 hh /= CON;
127 buf_plus = x; buf_minus = x; buf_plus(mu) += hh; buf_minus(mu) -= hh;
128#ifdef FOURTHORDER
129 buf_plus2 = x; buf_minus2 = x; buf_plus2(mu) += hh*2; buf_minus2 -= hh*2;
130 a(0,i) = (-(*func)(buf_plus2, p) + 8.0*(*func)(buf_plus, p)
131 - 8.0*(*func)(buf_minus, p) + (*func)(buf_minus2, p)) / (hh*12.0);
132#else
133 a(0,i) = ((*func)(buf_plus, p) - (*func)(buf_minus, p)) / (2.0*hh);
134#endif
135 fac = CON2;
136 for (REGISTER int j = 1; j <= i; j++) {
137 a(j,i) = (a(j-1,i)*fac - a(j-1,i-1))/(fac-1.0);
138 fac *= CON2;
139 errt = MAX (MATH__ fabs(a(j,i)-a(j-1,i)), MATH__ fabs(a(j,i)-a(j-1,i-1)));
140 if (errt <= err) {
141 err = errt;
142 ans = a(j,i);
143 }
144 }
145 if (MATH__ fabs (a(i,i)-a(i-1,i-1)) >= MATH__ fabs (SAFE*err)) break;
146 }
147 return ans;
148}
149
150
151INST(template <typename T> class Vector friend \
152 T Chisq (Vector<T>&, Vector<T>&, Vector<T>&);)
153
154template <typename T>
155T Chisq (Vector<T>& data, Vector<T>& func, Vector<T>& sig)
156 // calculates the chi-squared sum
157
158{
159 T chi ALIGN(MIN_ALIGN) = 0;
160 int len=data.size();
161
162 for(REGISTER int i=0;i<len;i++) chi+=sqr((data(i)-func(i))/sig(i));
163 return(chi);
164}
165
166
167INST(template <typename T> class Vector friend \
168 T Chisquare_2D (T (*func)(const Vector<T>&, const Vector<T>&), \
170
171template <typename T>
172T Chisquare_2D (T (*func)(const Vector<T>&, const Vector<T>&),
173 Vector<T>& param, Vector<T>& x, Vector<T>& y, Vector<T>& z, Vector<T>& sigma)
176{
177 Vector<T> arg(2);
178
179 T chi ALIGN(MIN_ALIGN) = 0, wfvaldiff;
180 int anzpkt = x.size();
181
182 for (REGISTER int i = 0; i < anzpkt; i++) {
183 arg(0) = x(i); arg(1) = y(i);
184 wfvaldiff = (z(i) - (*func)(param, arg)) / sigma(i);
185 chi += sqr (wfvaldiff);
186 }
187 return chi;
188}
189
190
191INST(template <typename T> class Vector friend \
192 TVector<T> Grid_Min_2D(T (*func)(const Vector<T>&, const Vector<T>&), \
194 Vector<T>&, Vector<T>&, \
195 Vector<T>&, Vector<T>&, \
196 long int, int, char);)
197
198template <typename T>
199TVector<T> Grid_Min_2D(T (*func)(const Vector<T>&, const Vector<T>&),
201 Vector<T>& sig, Vector<T>& pmin,
202 Vector<T>& pmax, Vector<T>& lambda,
203 long int res, int max_it, char v)
205{
206
207 int plen=pmin.size();
208 int xlen=x.size();
209 long int len=0;
210 Vector<T> p(pmin);
211 TVector<T> min_pos(pmin);
212 Vector<T> factor(plen);
213 Vector<T> arg(2);
214 Vector<T> fval(x.size());
215 Vector<T> index(plen);
216 Vector<T> b(0, plen);
217 Vector<T> a(0, plen);
218 T min ALIGN(MIN_ALIGN) = 0, chi=0 /*, err=0.0, fac=1e-8*/;
219
220 len = (long int) MATH__ pow ((double)res, plen);
221 for (int k=0;k<xlen;k++) { arg(0)=x(k); arg(1)=y(k); fval(k)=(*func)(p, arg); }
222 min=Chisq(z, fval, sig);
223 STD__ cout << "\n parameter space discretisation with " << len << " points in progress ... \n ";
224 for (REGISTER int j = 0; j < plen; j++)
225 factor(j) = (pmax(j) - pmin(j)) / ((T)res - (T)1);
226 for (long int i=0; i<len; i++) {
227 // linearize recursive for structure by basis trafo
228 if ( !Basis_Trafo(i, res, index) )
229 STD__ cerr << "\n error: basis trafo failed\n";
230 for (REGISTER int j=0; j<plen; j++)
231 p(j) = factor(j) * index(j) + pmin(j); //p-space discr.
232#if 0
233 //do max_it steepest gradient steps
234 for (int l=0; l<max_it; l++) {
235 // setup Vector
236 err=0.0;
237 for (int k=0; k<plen; k++) {
238 for (int j=0; j<xlen; j++) {
239 arg(0)=x(j); arg(1)=y(j);
240 b(k)+=(z(j)-(*func)(p, arg))/(sig(j)*sig(j))*
241 Partial_Del(func, p, arg, k, p(k)*fac, err);
242 }
243 }
244 // setup diagonal Matrix for steepest gradient const
245 err=0.0;
246 for (int k=0; k<plen; k++) {
247 for (REGISTER int j=0; j<xlen; j++) {
248 arg(0)=x(j); arg(1)=y(j);
249 a(k)+=sqr(Partial_Del(func, p, arg, k, p(k)*fac, err))/
250 (sig(j)*sig(j));
251 }
252 }
253 for (int k=0; k<plen; k++)
254 p(k)+=b(k)*lambda(k)/(a(k)+DELTAX);
255 }
256#endif
257 // calc func values with new parameter
258 for (int l=0; l<xlen; l++) { arg(0)=x(l); arg(1)=y(l); fval(l)=(*func)(p, arg); }
259 // calc chi2 sqared
260 chi=Chisq(z, fval, sig);
261 if ( chi<min ) { min=chi; min_pos=p; } //choose new min
262 if ( i%1000==0 ) STD__ cerr << i << "\t\t\t\r";
263#ifdef SIGHANDLE
264 if (sigint) { sigint--; return 0; }
265#endif
266 }
267 STD__ cout << " \n done! \n\n" << STD__ endl;
268 return min_pos;
269}
270
271
272INST(template <typename T> class Vector friend \
273 T LM_fit_2D(Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&, \
274 Vector<T>&, Vector<T>&,T (*func)(const Vector<T>&, const Vector<T>&), \
275 Vector<T>, Vector<T>&, T, int, char);)
276
277template <typename T>
278T LM_fit_2D(Vector<T>& x, Vector<T>& y, Vector<T>& z, Vector<T>& sig, Vector<T>& param,
279 Vector<T>& plow, Vector<T>& phigh,
280 T (*func)(const Vector<T>&, const Vector<T>&),
281 Vector<T> lambda, Vector<T>& lscale,
282 T tol, int iter, char ver)
287{
288 T chi ALIGN(MIN_ALIGN), chi_new, chi_min, chi_dif, err=0.0, fac=1.0e-8;
289 int len = x.size();
290 int plen = param.size();
291 Vector<T> param2(plen); // Vector<T> for new parameter set
292 Vector<T> param_best(plen); // Vector<T> for best parameter set
293 Vector<T> fval(len); // Vector for fit-func values
294 Vector<T> arg(2); // Vector for arguments of fit-func (2dim)
295
296 // comp chi-squared
297 chi = Chisquare_2D<T> (func, param, x, y, z, sig);
298 STD__ cout << " \n chi-squared with start parameters is: " << chi;
299 chi_min = chi;
300 // ini matrices
301 Matrix<T> a(0.0, plen,plen);
302 Matrix<T> b(0.0, plen,1);
303 STD__ cout << "\n initializing matrices and starting loop... \n";
304 int j=0; // iteration counter
305 param_best=param;
306 do {
307 int k;
308 // setup Matrix
309 for (k=0; k<plen; k++)
310 for (int l=0; l<plen; l++) {
311 for (int i=0; i<len; i++) {
312 arg(0) = x(i); arg(1)=y(i);
313 a(k,l) += Partial_Del(func, param, arg, k, param(k)*fac, err)*
314 Partial_Del(func, param, arg, l, param(l)*fac, err) /(sig(i)*sig(i));
315 }
316 //STD__ cerr << "\nDEBUG matrix:\n " << a << STD__ flush;
317 //STD__ cerr << "\nDEBUG param:\n " << param << STD__ flush;
318 //STD__ cerr << "\nDEBUG arg:\n " << arg << STD__ flush;
319 //STD__ cerr << "\nDEBUG delk:\n " << Partial_Del(func, param, arg, k, param(k)*fac, err) << STD__ flush;
320 //STD__ cerr << "\nDEBUG dell:\n " << Partial_Del(func, param, arg, l, param(l)*fac, err) << STD__ flush;
321 a(k,l) *= ((T)1+lambda(k)*(T)DELTA(k,l));
322 }
323 // setup Vector<T>
324 for (k=0;k<plen;k++) {
325 for (int i=0;i<len;i++) {
326 arg(0)=x(i); arg(1)=y(i);
327 b(k,0) += (z(i)-(*func)(param, arg))/(sig(i)*sig(i))*
328 Partial_Del(func, param, arg, k, param(k)*fac, err);
329 }
330 }
331 // solve equ a.x=b
332 char exceed = gaussj (a, b);
333 // calc new parameter
334 for (REGISTER int i=0;i<plen;i++) param2(i)=param(i)+b(i,0);
335 // check parameter range
336 exceed = 0;
337 for (REGISTER int f=0; f<plen; f++) {
338 if ((param2(f) > phigh(f)) && (phigh(f)!=plow(f)) ) exceed = 1;
339 if ((param2(f) < plow(f)) && (phigh(f)!=plow(f)) ) exceed = 1;
340 }
341 // calc chi2 sqared
342 chi_new = Chisquare_2D <T> (func, param2, x, y, z, sig);
343 chi_dif = MATH__ fabs (chi_new - chi);
344 if ((chi_new >= chi) || (exceed == 1)) lambda *= lscale(0);
345 //increase lambda cause downhill is exhausted or limits are exceeded
346 else {
347 // decrease lambda and update trial solution
348 lambda*=(T)1/lscale(1);
349 param=param2;
350 // update best est. param if new min is reached
351 if (chi_new<chi_min) {
352 chi_min=chi_new;
353 param_best=param;
354 }
355 }
356 chi=chi_new; // update chi
357 if (ver=='y' || ver=='Y')
358 STD__ cerr << "\n iteration " << j << " " << param <<
359 " " << param2 << " " << chi_new;
360#ifdef SIGHANDLE
361 if (sigint) { sigint--; param = param_best; return 1e38; }
362#endif
363 j++;
364 if (j%10 == 0) STD__ cerr << ".";
365 // end loop if tolerance is reached or number of iterations exceeded
366 } while( (chi_dif >= tol) && (j < iter) );
367 param = param_best; // return best parameter set found
368 STD__ cout << "\n loop finished after " << j << " iterations with last delta chi: "
369 << chi_dif << "\n and chi-squared: " << chi_new << STD__ endl;
370 return (chi_new);
371}
372
373
375
376#endif /* TBCI_LM_FIT_H */
377
#define NTAB
Definition LM_fit.h:89
const Vector< T > const Vector< T > const Vector< T > int mu
Definition LM_fit.h:99
#define SAFE
Definition LM_fit.h:90
#define BIG
Definition LM_fit.h:88
long int basis
Definition LM_fit.h:66
const Vector< T > const Vector< T > const Vector< T > & p
Definition LM_fit.h:98
long int Vector< T > & index
Definition LM_fit.h:69
#define DELTAX
Definition LM_fit.h:49
int xlen
Definition LM_fit.h:105
const Vector< T > const Vector< T > & x
Definition LM_fit.h:97
#define CON
Definition LM_fit.h:87
Vector< T > buf_minus(xlen)
const Vector< T > const Vector< T > const Vector< T > int T h
Definition LM_fit.h:99
const Vector< T > const Vector< T > const Vector< T > int T T & err
Definition LM_fit.h:102
Vector< T > buf_plus(xlen)
int i
Definition LM_fit.h:71
#define DELTA(i, j)
the kronecker delta
Definition LM_fit.h:53
#define CON2
Definition LM_fit.h:86
doublereal y
Definition TOMS_707.C:27
#define CSTD__
Definition basics.h:340
#define STD__
Definition basics.h:338
#define NAMESPACE_END
Definition basics.h:323
#define INST(x)
Definition basics.h:238
#define NAMESPACE_TBCI
Definition basics.h:317
#define REGISTER
Definition basics.h:108
#define MATH__
Definition basics.h:339
#define ALIGN(x)
Definition basics.h:444
#define MIN_ALIGN
Definition basics.h:421
#define MAX(a, b)
Definition basics.h:656
#define T
Definition bdmatlib.cc:20
Temporary Base Class Idiom: Class TVector is used for temporary variables.
Definition vector.h:73
unsigned long size() const
Definition vector.h:104
double fabs(const TBCI__ cplx< T > &c)
Definition cplx.h:746
T arg(const TBCI__ cplx< T > &c)
Definition cplx.h:690
TBCI__ cplx< T > pow(const TBCI__ cplx< T > &z, const double n)
Definition cplx.h:761
cplx< T > sqr(const cplx< T > &c)
Definition cplx.h:449
TBCI__ cplx< T > log(const TBCI__ cplx< T > &z)
Definition cplx.h:771
NAMESPACE_END NAMESPACE_CSTD TBCI__ cplx< T > sqrt(const TBCI__ cplx< T > &z)
Definition cplx.h:751
#define min(a, b)
Definition f2c.h:180
tm fac
Definition f_matrix.h:1052
F_TMatrix< T > b
Definition f_matrix.h:736
NAMESPACE_TBCI char gaussj(Matrix< T > &a, Matrix< T > &b)
const unsigned TMatrix< T > const Matrix< T > * a
const unsigned TMatrix< T > * res