00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef TBCI_LM_FIT_H
00023 #define TBCI_LM_FIT_H
00024
00025 #include "basics.h"
00026 #include "vector.h"
00027 #include "matrix.h"
00028 #include "constants.h"
00029 #include "solver/gauss_jordan.h"
00030
00031
00032 #ifdef HAVE_SIGNALS
00033 # include <signal.h>
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043 NAMESPACE_TBCI
00044
00045 #ifdef PRAGMA_I
00046 # pragma interface "LM_fit.h"
00047 #endif
00048
00049 #define DELTAX 1e-30
00050
00052
00053 #define DELTA(i,j) ((i==j)?1:0)
00054
00055
00056
00057
00058
00059
00060
00061
00062 INST(template <typename T> class Vector friend \
00063 int Basis_Trafo (long int, long int, Vector<T>&);)
00064
00065 template <typename T>
00066 int Basis_Trafo (long int value, long int basis, Vector<T>& index)
00067
00068
00069 {
00070 int n = index.size();
00071 int i = 0;
00072
00073 index = (T)0;
00074 if (value == 0) return 1;
00075 if (n < (int)CSTD__ ceil (MATH__ sqrt(2*MATH__ log((double)value) / MATH__ log((double)basis))) || basis <= 1) return 0;
00076 while (value > 0)
00077 {
00078 index(i) = value%basis;
00079 value /= basis;
00080 i++;
00081 }
00082 return 1;
00083 }
00084
00085
00086 #define CON2 2.0
00087 #define CON SQRT2
00088 #define BIG 1.0e30
00089 #define NTAB 10
00090 #define SAFE 2.0
00091
00092 INST(template <typename T> class Vector friend \
00093 T Partial_Del (T (*func)(const Vector<T>&, const Vector<T>&), \
00094 const Vector<T>&, const Vector<T>&, \
00095 int, T, T&);)
00096 template <typename T>
00097 T Partial_Del (T (*func)(const Vector<T>&, const Vector<T>&),
00098 const Vector<T>& x, const Vector<T>& p,
00099 int mu, T h, T& err)
00100
00101
00102 {
00103
00104 T errt ALIGN(MIN_ALIGN), fac, hh, ans = (T)0;
00105 int xlen = x.size();
00106 Matrix<T> a(NTAB,NTAB);
00107 Vector<T> buf_plus(xlen);
00108 Vector<T> buf_minus(xlen);
00109 #ifdef FOURTHORDER
00110 Vector<T> buf_plus2(xlen);
00111 Vector<T> buf_minus2(xlen);
00112 #endif
00113 if (mu >= xlen)
00114 STD__ cerr << "\n error: partial_del: derivate variable index out of range \n";
00115 hh = h ;
00116 buf_plus = x; buf_minus = x; buf_plus(mu) += hh; buf_minus(mu) -= hh;
00117 #ifdef FOURTHORDER
00118 buf_plus2 = x; buf_minus2 = x; buf_plus2(mu) += hh*2; buf_minus2 -= hh*2;
00119 a(0,0) = (-(*func)(buf_plus2, p) + 8.0*(*func)(buf_plus, p)
00120 - 8.0*(*func)(buf_minus, p) + (*func)(buf_minus2, p)) / (hh*12.0);
00121 #else
00122 a(0,0) = ((*func)(buf_plus, p) - (*func)(buf_minus, p)) / (2.0*hh);
00123 #endif
00124 err = BIG;
00125 for (int i = 1; i < NTAB; i++) {
00126 hh /= CON;
00127 buf_plus = x; buf_minus = x; buf_plus(mu) += hh; buf_minus(mu) -= hh;
00128 #ifdef FOURTHORDER
00129 buf_plus2 = x; buf_minus2 = x; buf_plus2(mu) += hh*2; buf_minus2 -= hh*2;
00130 a(0,i) = (-(*func)(buf_plus2, p) + 8.0*(*func)(buf_plus, p)
00131 - 8.0*(*func)(buf_minus, p) + (*func)(buf_minus2, p)) / (hh*12.0);
00132 #else
00133 a(0,i) = ((*func)(buf_plus, p) - (*func)(buf_minus, p)) / (2.0*hh);
00134 #endif
00135 fac = CON2;
00136 for (register int j = 1; j <= i; j++) {
00137 a(j,i) = (a(j-1,i)*fac - a(j-1,i-1))/(fac-1.0);
00138 fac *= CON2;
00139 errt = MAX (MATH__ fabs(a(j,i)-a(j-1,i)), MATH__ fabs(a(j,i)-a(j-1,i-1)));
00140 if (errt <= err) {
00141 err = errt;
00142 ans = a(j,i);
00143 }
00144 }
00145 if (MATH__ fabs (a(i,i)-a(i-1,i-1)) >= MATH__ fabs (SAFE*err)) break;
00146 }
00147 return ans;
00148 }
00149
00150
00151 INST(template <typename T> class Vector friend \
00152 T Chisq (Vector<T>&, Vector<T>&, Vector<T>&);)
00153
00154 template <typename T>
00155 T Chisq (Vector<T>& data, Vector<T>& func, Vector<T>& sig)
00156
00157
00158 {
00159 T chi ALIGN(MIN_ALIGN) = 0;
00160 int len=data.size();
00161
00162 for(register int i=0;i<len;i++) chi+=sqr((data(i)-func(i))/sig(i));
00163 return(chi);
00164 }
00165
00166
00167 INST(template <typename T> class Vector friend \
00168 T Chisquare_2D (T (*func)(const Vector<T>&, const Vector<T>&), \
00169 Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&);)
00170
00171 template <typename T>
00172 T Chisquare_2D (T (*func)(const Vector<T>&, const Vector<T>&),
00173 Vector<T>& param, Vector<T>& x, Vector<T>& y, Vector<T>& z, Vector<T>& sigma)
00176 {
00177 Vector<T> arg(2);
00178
00179 T chi ALIGN(MIN_ALIGN) = 0, wfvaldiff;
00180 int anzpkt = x.size();
00181
00182 for (register int i = 0; i < anzpkt; i++) {
00183 arg(0) = x(i); arg(1) = y(i);
00184 wfvaldiff = (z(i) - (*func)(param, arg)) / sigma(i);
00185 chi += sqr (wfvaldiff);
00186 }
00187 return chi;
00188 }
00189
00190
00191 INST(template <typename T> class Vector friend \
00192 TVector<T> Grid_Min_2D(T (*func)(const Vector<T>&, const Vector<T>&), \
00193 Vector<T>&, Vector<T>&, Vector<T>&, \
00194 Vector<T>&, Vector<T>&, \
00195 Vector<T>&, Vector<T>&, \
00196 long int, int, char);)
00197
00198 template <typename T>
00199 TVector<T> Grid_Min_2D(T (*func)(const Vector<T>&, const Vector<T>&),
00200 Vector<T>& x, Vector<T>& y, Vector<T>& z,
00201 Vector<T>& sig, Vector<T>& pmin,
00202 Vector<T>& pmax, Vector<T>& lambda,
00203 long int res, int max_it, char v)
00205 {
00206
00207 int plen=pmin.size();
00208 int xlen=x.size();
00209 long int len=0;
00210 Vector<T> p(pmin);
00211 TVector<T> min_pos(pmin);
00212 Vector<T> factor(plen);
00213 Vector<T> arg(2);
00214 Vector<T> fval(x.size());
00215 Vector<T> index(plen);
00216 Vector<T> b(0, plen);
00217 Vector<T> a(0, plen);
00218 T min ALIGN(MIN_ALIGN) = 0, chi=0 ;
00219
00220 len = (long int) MATH__ pow ((double)res, plen);
00221 for (int k=0;k<xlen;k++) { arg(0)=x(k); arg(1)=y(k); fval(k)=(*func)(p, arg); }
00222 min=Chisq(z, fval, sig);
00223 STD__ cout << "\n parameter space discretisation with " << len << " points in progress ... \n ";
00224 for (register int j = 0; j < plen; j++)
00225 factor(j) = (pmax(j) - pmin(j)) / ((T)res - (T)1);
00226 for (long int i=0; i<len; i++) {
00227
00228 if ( !Basis_Trafo(i, res, index) )
00229 STD__ cerr << "\n error: basis trafo failed\n";
00230 for (register int j=0; j<plen; j++)
00231 p(j) = factor(j) * index(j) + pmin(j);
00232 #if 0
00233
00234 for (int l=0; l<max_it; l++) {
00235
00236 err=0.0;
00237 for (int k=0; k<plen; k++) {
00238 for (int j=0; j<xlen; j++) {
00239 arg(0)=x(j); arg(1)=y(j);
00240 b(k)+=(z(j)-(*func)(p, arg))/(sig(j)*sig(j))*
00241 Partial_Del(func, p, arg, k, p(k)*fac, err);
00242 }
00243 }
00244
00245 err=0.0;
00246 for (int k=0; k<plen; k++) {
00247 for (register int j=0; j<xlen; j++) {
00248 arg(0)=x(j); arg(1)=y(j);
00249 a(k)+=sqr(Partial_Del(func, p, arg, k, p(k)*fac, err))/
00250 (sig(j)*sig(j));
00251 }
00252 }
00253 for (int k=0; k<plen; k++)
00254 p(k)+=b(k)*lambda(k)/(a(k)+DELTAX);
00255 }
00256 #endif
00257
00258 for (int l=0; l<xlen; l++) { arg(0)=x(l); arg(1)=y(l); fval(l)=(*func)(p, arg); }
00259
00260 chi=Chisq(z, fval, sig);
00261 if ( chi<min ) { min=chi; min_pos=p; }
00262 if ( i%1000==0 ) STD__ cerr << i << "\t\t\t\r";
00263 #ifdef SIGHANDLE
00264 if (sigint) { sigint--; return 0; }
00265 #endif
00266 }
00267 STD__ cout << " \n done! \n\n" << STD__ endl;
00268 return min_pos;
00269 }
00270
00271
00272 INST(template <typename T> class Vector friend \
00273 T LM_fit_2D(Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&, Vector<T>&, \
00274 Vector<T>&, Vector<T>&,T (*func)(const Vector<T>&, const Vector<T>&), \
00275 Vector<T>, Vector<T>&, T, int, char);)
00276
00277 template <typename T>
00278 T LM_fit_2D(Vector<T>& x, Vector<T>& y, Vector<T>& z, Vector<T>& sig, Vector<T>& param,
00279 Vector<T>& plow, Vector<T>& phigh,
00280 T (*func)(const Vector<T>&, const Vector<T>&),
00281 Vector<T> lambda, Vector<T>& lscale,
00282 T tol, int iter, char ver)
00287 {
00288 T chi ALIGN(MIN_ALIGN), chi_new, chi_min, chi_dif, err=0.0, fac=1.0e-8;
00289 int len = x.size();
00290 int plen = param.size();
00291 Vector<T> param2(plen);
00292 Vector<T> param_best(plen);
00293 Vector<T> fval(len);
00294 Vector<T> arg(2);
00295
00296
00297 chi = Chisquare_2D<T> (func, param, x, y, z, sig);
00298 STD__ cout << " \n chi-squared with start parameters is: " << chi;
00299 chi_min = chi;
00300
00301 Matrix<T> a(0.0, plen,plen);
00302 Matrix<T> b(0.0, plen,1);
00303 STD__ cout << "\n initializing matrices and starting loop... \n";
00304 int j=0;
00305 param_best=param;
00306 do {
00307 int k;
00308
00309 for (k=0; k<plen; k++)
00310 for (int l=0; l<plen; l++) {
00311 for (int i=0; i<len; i++) {
00312 arg(0) = x(i); arg(1)=y(i);
00313 a(k,l) += Partial_Del(func, param, arg, k, param(k)*fac, err)*
00314 Partial_Del(func, param, arg, l, param(l)*fac, err) /(sig(i)*sig(i));
00315 }
00316
00317
00318
00319
00320
00321 a(k,l) *= ((T)1+lambda(k)*(T)DELTA(k,l));
00322 }
00323
00324 for (k=0;k<plen;k++) {
00325 for (int i=0;i<len;i++) {
00326 arg(0)=x(i); arg(1)=y(i);
00327 b(k,0) += (z(i)-(*func)(param, arg))/(sig(i)*sig(i))*
00328 Partial_Del(func, param, arg, k, param(k)*fac, err);
00329 }
00330 }
00331
00332 char exceed = gaussj (a, b);
00333
00334 for (register int i=0;i<plen;i++) param2(i)=param(i)+b(i,0);
00335
00336 exceed = 0;
00337 for (register int f=0; f<plen; f++) {
00338 if ((param2(f) > phigh(f)) && (phigh(f)!=plow(f)) ) exceed = 1;
00339 if ((param2(f) < plow(f)) && (phigh(f)!=plow(f)) ) exceed = 1;
00340 }
00341
00342 chi_new = Chisquare_2D <T> (func, param2, x, y, z, sig);
00343 chi_dif = MATH__ fabs (chi_new - chi);
00344 if ((chi_new >= chi) || (exceed == 1)) lambda *= lscale(0);
00345
00346 else {
00347
00348 lambda*=(T)1/lscale(1);
00349 param=param2;
00350
00351 if (chi_new<chi_min) {
00352 chi_min=chi_new;
00353 param_best=param;
00354 }
00355 }
00356 chi=chi_new;
00357 if (ver=='y' || ver=='Y')
00358 STD__ cerr << "\n iteration " << j << " " << param <<
00359 " " << param2 << " " << chi_new;
00360 #ifdef SIGHANDLE
00361 if (sigint) { sigint--; param = param_best; return 1e38; }
00362 #endif
00363 j++;
00364 if (j%10 == 0) STD__ cerr << ".";
00365
00366 } while( (chi_dif >= tol) && (j < iter) );
00367 param = param_best;
00368 STD__ cout << "\n loop finished after " << j << " iterations with last delta chi: "
00369 << chi_dif << "\n and chi-squared: " << chi_new << STD__ endl;
00370 return (chi_new);
00371 }
00372
00373
00374 NAMESPACE_END
00375
00376 #endif
00377