source: Sophya/trunk/SophyaLib/NTools/generalfit.cc@ 914

Last change on this file since 914 was 914, checked in by ansari, 25 years ago

documentation cmv 13/4/00

File size: 47.7 KB
Line 
1#include "machdefs.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <iostream.h>
5#include <math.h>
6#ifdef __MWERKS__
7 #include "mwerksmath.h" // Portage mac D. Y.
8#include "unixmac.h"
9#endif
10#include <string.h>
11#include <string>
12
13#include "pexceptions.h"
14#include "generalfit.h"
15#include "sopemtx.h"
16
17#define EPS_FIT_MIN 1.e-8
18
19//================================================================
20// GeneralFunction
21//================================================================
22
23//////////////////////////////////////////////////////////////////////
24/*!
25 Creation d'une fonction de `nVar' variables et `nPar' parametres:
26 \f$ F[x(1),x(2),x(3),...x(nVar) : a(1),a(2),a(3),...,a(nPar)] \f$
27*/
28GeneralFunction::GeneralFunction(unsigned int nVar, unsigned int nPar)
29 : mNVar(nVar), mNPar(nPar)
30{
31 ASSERT( nVar > 0 && nPar > 0 );
32 deltaParm = new double[nPar];
33 tmpParm = new double[nPar];
34 END_CONSTRUCTOR
35}
36
37GeneralFunction::~GeneralFunction()
38{
39 delete[] deltaParm;
40 delete[] tmpParm;
41}
42
43//////////////////////////////////////////////////////////////////////
44/*!
45 Valeur et Derivees de la fonction (fct virtuelle par defaut).
46*/
47double GeneralFunction::Val_Der(double const xp[], double const* parm
48 , double *DgDpar)
49{
50 for(int i=0;i<mNPar;i++) tmpParm[i] = parm[i];
51 {for(int i=0;i<mNPar;i++) {
52 double d = deltaParm[i];
53 if(d==0.) { DgDpar[i] = 0.; continue;}
54 tmpParm[i] -= d/2.;
55 double vg = Value(xp,tmpParm);
56 tmpParm[i] += d;
57 double vd = Value(xp,tmpParm);
58 DgDpar[i] = (vd - vg)/d;
59 tmpParm[i] = parm[i];
60 }}
61 return Value(xp, parm);
62}
63
64//////////////////////////////////////////////////////////////////////
65/*!
66 Definition de la variation du parametre numPar
67 pour calculer la derivee automatiquement.
68*/
69void GeneralFunction::SetDeltaParm(int numPar, double d)
70{
71 ASSERT(numPar >= 0 && numPar < mNPar);
72 deltaParm[numPar] = d;
73}
74
75
76/*!
77 Idem precedente fonction mais pour tous les parametres
78*/
79void GeneralFunction::SetDeltaParm(double const* dparam)
80{
81 for(int i=0;i<mNPar;i++) deltaParm[i] = dparam[i];
82}
83
84//================================================================
85// GeneralFunc
86//================================================================
87
88/////////////////////////////////////////////////////////////////
89/*!
90 Createur, on passe le nom ``fun'' de la fonction a la mode C.
91 On peut optionellement egalement passer le nom de la fonction
92 ``funder'' qui retourne les valeurs des derivees par rapport
93 aux parametres du fit.
94 \verbatim
95 ----------------------
96 Exemple d'utilisation:
97 ----------------------
98 include "generalfit.h"
99 ...
100 double gaussc(double const* x,double const* p);
101 double d_gaussc(double const* x,double const* p,double* dp);
102 ...
103 main {
104 ...
105 // Fit SANS calcul automatique des derivees
106 GeneralFunc myfunc(2,7,gaussc);
107 GeneralFit myfit(&myfunc);
108 ...
109 myfit.Fit();
110 ...
111 // Fit AVEC calcul automatique des derivees
112 GeneralFunc myfunc(2,7,gaussc,d_gaussc);
113 GeneralFit myfit(&myfunc);
114 ...
115 myfit.Fit();
116 }
117 // Definition de la fonction a fitter a la mode C
118 double gaussc(double const* x,double const* p)
119 // Fonction: X=(x[0]-p[1])/p[3], Y=(x[1]-p[2])/p[4],
120 // f = p[0]*exp{-0.5*[X^2+Y^2-2*p[5]*X*Y]} + p[6]
121 {
122 double X = (x[0]-p[1])/p[3];
123 double Y = (x[1]-p[2])/p[4];
124 return p[0]*exp(-(X*X+Y*Y-2*p[5]*X*Y)/2)+p[6];
125 }
126 // Definition de la fonction des derivees / parametres
127 // Cette fonction retourne aussi la valeur de la fonction a fitter.
128 double d_gaussc(double const* x,double const* p,double* dp)
129 {
130 dp[0] = derivee de gaussc par rapport au parametre p[0]
131 ...
132 dp[6] = derivee de gaussc par rapport au parametre p[6]
133 return gaussc(x,p);
134 }
135 \endverbatim
136*/
137GeneralFunc::GeneralFunc(unsigned int nvar, unsigned int npar
138 , double (*fun) (double const*, double const*)
139 , double (*funder) (double const*, double const*, double*) )
140: GeneralFunction(nvar,npar), tmpFun(fun), tmpFunDer(funder)
141{
142}
143
144GeneralFunc::~GeneralFunc()
145{
146}
147
148double GeneralFunc::Value(double const xp[], double const* Par)
149{
150return tmpFun(xp,Par);
151}
152
153double GeneralFunc::Val_Der(double const xp[],double const* parm, double* DgDpar)
154{
155if(tmpFunDer) return tmpFunDer(xp,parm,DgDpar);
156 else return GeneralFunction::Val_Der(xp,parm,DgDpar);
157}
158
159//================================================================
160// GeneralXi2
161//================================================================
162
163//////////////////////////////////////////////////////////////////////
164/*!
165//
166 Creation d'un Xi2 de `nPar' parametres.
167 \f$ Xi2[a(1),a(2),a(3),...,a(nPar)] \f$
168*/
169GeneralXi2::GeneralXi2(unsigned int nPar)
170 : mNPar(nPar)
171{
172 ASSERT( nPar>0 );
173 deltaParm = new double[nPar];
174 END_CONSTRUCTOR
175}
176
177GeneralXi2::~GeneralXi2()
178{
179 delete[] deltaParm;
180}
181
182//////////////////////////////////////////////////////////////////////
183/*!
184 Derivee du Xi2 par rapport au parametre `i'
185 pour les valeurs `parm' des parametres.
186*/
187double GeneralXi2::Derivee(GeneralFitData& data, int i, double* parm)
188{
189 int dum;
190 double d = deltaParm[i];
191 parm[i] -= d/2.;
192 double vg = Value(data, parm,dum);
193 parm[i] += d;
194 double vd = Value(data, parm,dum);
195 parm[i] -= d/2.;
196 return (vd - vg)/d;
197}
198
199/*!
200 Derivee seconde du Xi2 par rapport aux parametres `i' et `j'
201 pour les valeurs `parm' des parametres. Attention, cette fonction
202 calcule d/di(dC2/dj), valeur qui est numeriquement differente
203 de d/dj(dC2/di).
204 \verbatim
205
206 **** Remarque: Derivee2 = dXi2/dPi.dPj represente le Hessien.
207 Derivee2(k,l)= dXi2/dPk.dPl
208 = 2*SUMi{1/Si^2*[df(xi;P)/dPk * df(xi;P)/dPl]
209 + [yi-f(xi;P)] * df(xi;P)/dPk.dPl }
210 ou (xi,yi) sont les points de mesure. "Si" l'erreur sur le point i
211 SUMi represente la somme sur les points de mesure
212 f(x;P) represente le modele parametrique a fitter
213 "P" represente l'ensemble des parametres et "Pi" le ieme parametre
214 Les composantes du Hessien dependent des derivees 1ere et 2sd du modele
215 a fitter f(x;P) selon les parametres "Pi". La prise en compte des derivees
216 secondes est un facteur destabilisant. De plus le facteur [yi-f(xi;P)]
217 devant la derivee 2sd est seulement l'erreur de mesure aleatoire qui
218 n'est pas correlee avec le modele. Le terme avec la derivee 2sd
219 tend donc a s'annuler et peut donc etre omis.
220 (cf. Numerical Recipes in C, chap 15 Modeling of Data, Nonlinear Models,
221 Calculation of the Gradient and Hessian p682,683)
222
223 **** Conseil: Il est conseille a l'utilisateur de sur-ecrire
224 la fonction virtuelle Derivee2 et de la remplacer par:
225 Derivee2(k,l) = 2*SUMi{1/Si^2*[df(xi;P)/dPk * df(xi;P)/dPl]}
226 \endverbatim
227*/
228double GeneralXi2::Derivee2(GeneralFitData& data, int i, int j, double* parm)
229{
230 double d = deltaParm[i];
231 parm[i] -= d/2.;
232 double vg = Derivee(data,j,parm);
233 parm[i] += d;
234 double vd = Derivee(data,j,parm);
235 parm[i] -= d/2.;
236 d = (vd - vg)/d;
237 return d;
238}
239
240//////////////////////////////////////////////////////////////////////
241/*!
242 Definition de la variation 'd' du parametre 'numPar'
243 pour calculer la derivee automatiquement.
244*/
245void GeneralXi2::SetDeltaParm(int numPar, double d)
246{
247 ASSERT(numPar >= 0 && numPar < mNPar);
248
249 deltaParm[numPar] = d;
250}
251
252/*!
253 Idem precedente fonction mais pour tous les parametres.
254*/
255void GeneralXi2::SetDeltaParm(double const* dparam)
256{
257 for(int i=0;i<mNPar;i++) deltaParm[i] = dparam[i];
258}
259
260//================================================================
261// GeneralFit
262//================================================================
263// Christophe 8/11/93 La Silla
264// re-codage C++ 16/01/96 Saclay
265//////////////////////////////////////////////////////////////////////
266/*!
267 Creation d'une classe de fit pour la `GeneralFunction f'.
268*/
269GeneralFit::GeneralFit(GeneralFunction* f)
270 : mNVar (f->NVar()),
271 mNPar (f->NPar()),
272 mFunction (f),
273 mFuncXi2 (NULL),
274
275 Param (f->NPar()),
276 errParam (f->NPar()),
277 stepParam (f->NPar()),
278 minParam (f->NPar()),
279 maxParam (f->NPar()),
280 minStepDeriv (f->NPar()),
281 Eps (f->NPar()),
282
283 ATGA (f->NPar(), f->NPar()),
284 BETA (f->NPar()),
285 ATGA_Try (f->NPar(), f->NPar()),
286 BETA_Try (f->NPar()),
287 C (f->NPar()),
288 D (f->NPar())
289{
290 ASSERT(mNVar>0 && mNPar>0);
291 ASSERT(mNPar<1000000);
292
293 TRY {
294 General_Init();
295 } CATCHALL {
296 THROW_SAME;
297 } ENDTRY
298
299 END_CONSTRUCTOR
300}
301
302/*!
303 Creation d'une classe de fit pour le `GeneralXi2 f'.
304 L'emploi de cette methode n'est pas conseillee car elle
305 calcule automatiquement la derivee 2sd du Xi2 par rapport
306 aux parametres, ce qui entraine un manque de robustesse
307 et qui ne garanti pas que la matrice de covariance soit
308 definie positive (il est possible de surecrire
309 la methode virtuelle Derivee2 pour palier ce probleme).
310*/
311GeneralFit::GeneralFit(GeneralXi2* f)
312 : mNVar (0),
313 mNPar (f->NPar()),
314 mFunction (NULL),
315 mFuncXi2 (f),
316
317 Param (f->NPar()),
318 errParam (f->NPar()),
319 stepParam (f->NPar()),
320 minParam (f->NPar()),
321 maxParam (f->NPar()),
322 minStepDeriv (f->NPar()),
323 Eps (f->NPar()),
324
325 ATGA (f->NPar(), f->NPar()),
326 BETA (f->NPar()),
327 ATGA_Try (f->NPar(), f->NPar()),
328 BETA_Try (f->NPar()),
329 C (f->NPar()),
330 D (f->NPar())
331{
332 ASSERT( mNPar>0 );
333 ASSERT( mNPar < 1000000 );
334
335 TRY {
336 General_Init();
337 } CATCHALL {
338 THROW_SAME;
339 } ENDTRY
340
341 END_CONSTRUCTOR
342}
343
344//
345void GeneralFit::General_Init(void)
346// Initialisation des diverses variables
347{
348 mNtry = 0;
349 mNParFree = mNPar;
350 mNParBound = 0;
351
352 mData = NULL;
353
354 fixParam = NULL;
355 boundParam = NULL;
356 nameParam = NULL;
357
358 Lambda_Fac = 10.;
359 stopChi2 = 0.01;
360 maxStep = 100;
361 nStopMx = 3;
362 stopChi2SMx = stopChi2;
363 nStopLent = 0;
364 debugLevel = 0;
365 FileStep = NULL;
366
367 Chi2 = 0.;
368 mNddl = -1;
369 nStep = 0;
370 nStop = 0;
371 nStopL = 0;
372 Lambda = 0.001;
373
374 GetIntEnv("PDEBUG_GENERALFIT",debugLevel);
375
376 TRY {
377 fixParam = new unsigned short int[mNPar];
378 boundParam = new unsigned short int[mNPar];
379 nameParam = new string[mNPar];
380 } CATCHALL {
381 cout<<"GeneralFit::GeneralFit Impossible d'allouer l'espace"<<endl;
382 THROW_SAME;
383 } ENDTRY
384
385 Param = (double) 0.;
386 errParam = (double) 0.;
387 stepParam = (double) 1.;
388 minParam = (double) 1.;
389 maxParam = (double) -1.;
390 minStepDeriv = (double) 0.;
391 Eps = (double) EPS_FIT_MIN;
392 char str[8];
393 for(int i=0;i<mNPar;i++) {
394 sprintf(str,"P%d",i);
395 fixParam[i] = 0;
396 boundParam[i] = 0;
397 nameParam[i] = str;
398 }
399}
400
401GeneralFit::~GeneralFit()
402{
403 delete[] fixParam;
404 delete[] boundParam;
405 delete[] nameParam;
406 if(FileStep!=NULL) fclose(FileStep);
407}
408
409//////////////////////////////////////////////////////////////////////
410/*!
411 Pour ecrire les iterations dans le fichier filename
412*/
413void GeneralFit::WriteStep(char *filename)
414{
415
416#if defined(__DECCXX) || defined(__KCC__) || defined(__aCC__)
417if(filename==NULL) filename = const_cast<char *>("generalfit.iter");
418#else
419if(filename==NULL) filename = "generalfit.iter";
420#endif
421FileStep = fopen(filename,"w");
422if(FileStep==NULL) THROW(nullPtrErr);
423}
424
425/*!
426 Niveau de debug
427 (voir aussi la variable d'environnement PDEBUG_GENERALFIT).
428*/
429void GeneralFit::SetDebug(int level)
430{
431 debugLevel = ( level < 0 ) ? 0: level;
432 if(debugLevel>0) cout<<"SetDebug_level "<<debugLevel<<endl;
433}
434
435/*!
436 Nombre maximum d'iterations permis.
437*/
438void GeneralFit::SetMaxStep(int n)
439{
440 maxStep = ( n <= 1 ) ? 100: n;
441 if(debugLevel>0) cout<<"SetMaxStep "<<maxStep<<endl;
442}
443
444/*!
445 Facteur de multiplication/division de Lambda selon
446 que le Chi2 a augmente ou diminue.
447*/
448void GeneralFit::SetLambda_Fac(double fac)
449{
450 Lambda_Fac = (fac>1.) ? fac : 10.;
451}
452
453/*!
454 Critere de convergence sur le Chi2.
455*/
456void GeneralFit::SetStopChi2(double s)
457{
458 stopChi2 = ( s <= 0. ) ? 0.01: s;
459 if(debugLevel>0) cout<<"SetStopChi2 "<<stopChi2<<endl;
460}
461
462/*!
463 Precision des calculs (cf \ref GeneralFit_Fit "descriptif general").
464*/
465void GeneralFit::SetEps(double ep)
466{
467 ep = (ep<=0.) ? EPS_FIT_MIN: ep;
468 if(debugLevel>0) cout<<"SetEps "<<ep<<endl;
469 for(int i=0;i<mNPar;i++) SetEps(i,ep);
470}
471
472/*!
473 Precision des calculs pour le parametre n.
474*/
475void GeneralFit::SetEps(int n,double ep)
476{
477 ASSERT(n>=0 && n<mNPar);
478 Eps(n) = (ep<=0.) ? EPS_FIT_MIN: ep;
479 if(debugLevel>0) cout<<"SetEps("<<n<<") = "<<Eps(n)<<endl;
480}
481
482/*!
483 Critere de convergence sur le nombre de stop en chi2
484 dans le cas ou le chi2 augmente de moins de stopchi2
485 (cf \ref GeneralFit_Fit "descriptif general").
486
487 Si nstopmx<=0, alors ce critere de convergence n'est pas applique.
488
489 Si stopchi2<=0, alors la valeur generale mise par SetStopChi2()
490 est utilisee.
491*/
492void GeneralFit::SetStopMx(int nstopmx,double stopchi2)
493{
494 nStopMx = (nstopmx>0) ? nstopmx : 0;
495 stopChi2SMx = (stopchi2>0.) ? stopchi2 : stopChi2;
496 if(debugLevel>0) cout<<"SetStopMx: nStopMx="<<nStopMx
497 <<" stopChi2SMx="<<stopChi2SMx<<endl;
498}
499
500/*!
501 Critere de convergence sur le nombre de stop en chi2
502 dans le cas ou le chi2 diminue (cf \ref GeneralFit_Fit "descriptif general").
503
504 Si nstopl<=0, alors ce critere de convergence n'est pas applique.
505*/
506void GeneralFit::SetStopLent(int nstoplent)
507{
508 nStopLent = (nstoplent>0) ? nstoplent : 0;
509 if(debugLevel>0) cout<<"SetStopLent "<<nStopLent<<endl;
510}
511
512//////////////////////////////////////////////////////////////////////
513/*!
514 Pour changer la fonction a fitter en cours de route
515 (On ne peut passer d'un fit sur une GeneralFunction
516 a un fit sur un GeneralXi2 sans recreer la classe).
517*/
518void GeneralFit::SetFunction(GeneralFunction* f)
519{
520 ASSERT( mFuncXi2 == NULL );
521 ASSERT( f != NULL );
522 ASSERT( f->NVar() == mNVar );
523 ASSERT( f->NPar() == mNPar );
524 mFunction = f;
525 if(debugLevel>0) cout<<"SetFunction "<<mFunction<<endl;
526}
527
528/*!
529 Pour changer le Xi2 a fitter en cours de route
530 (On ne peut passer d'un fit sur une GeneralFunction
531 a un fit sur un GeneralXi2 sans recreer la classe).
532*/
533void GeneralFit::SetFuncXi2(GeneralXi2* f)
534{
535 ASSERT( mFunction == NULL );
536 ASSERT( f != NULL );
537 ASSERT( f->NPar() == mNPar );
538 mFuncXi2 = f;
539 if(debugLevel>0) cout<<"SetFuncXi2 "<<mFuncXi2<<endl;
540}
541
542//////////////////////////////////////////////////////////////////////
543/*!
544 Pour connecter une structure de donnees.
545*/
546void GeneralFit::SetData(GeneralFitData* data)
547{
548 ASSERT( data->NVar()==mNVar );
549 mData = data;
550 mNddl = mData->NDataGood() - mNParFree;
551 if(debugLevel>0)
552 cout<<"SetData "<<mData<<" data pour "<<mNddl<<" ddl"<<endl;
553}
554
555//////////////////////////////////////////////////////////////////////
556/*!
557 Definition du parametre "n" a fitter.
558*/
559void GeneralFit::SetParam(int n,double value,double step
560 ,double min,double max)
561{
562 ASSERT(n>=0 && n<mNPar);
563
564 Param(n) = value;
565 if(step>0.) {
566 if( fixParam[n] ) { fixParam[n]=0; mNParFree++;}
567 } else {
568 if( ! fixParam[n] ) { fixParam[n]=1; mNParFree--;}
569 }
570 stepParam(n) = step;
571 minParam(n) = min;
572 maxParam(n) = max;
573 if(max>min) {
574 if( ! boundParam[n] ) {boundParam[n]=1; mNParBound++;}
575 } else {
576 if( boundParam[n] ) {boundParam[n]=0; mNParBound--;}
577 }
578
579 if(debugLevel) {cout<<"Set_"; PrintParm(n);}
580}
581
582/*!
583 Definition du parametre "n" a fitter
584*/
585void GeneralFit::SetParam(int n, string const& name
586 ,double value,double step,double min,double max)
587{
588 ASSERT(n>=0 && n<mNPar);
589 SetParam(n,value,step,min,max);
590 nameParam[n] = name;
591 if(debugLevel) {cout<<"Set_Param "; PrintParm(n);}
592}
593
594/*!
595 Definition du parametre "n" a fitter
596*/
597void GeneralFit::SetParam(int n,double value)
598{
599 ASSERT(n>=0 && n<mNPar);
600 Param(n) = value;
601 if(debugLevel) {cout<<"Set_Param "; PrintParm(n);}
602}
603
604//////////////////////////////////////////////////////////////////////
605/*!
606 Definition du pas de depart du parametre "n"
607 Si negatif ou nul, parametre fixe.
608*/
609void GeneralFit::SetStep(int n,double step)
610{
611 ASSERT(n>=0 && n<mNPar);
612 if(step>0.) {
613 if( fixParam[n] ) { fixParam[n]=0; mNParFree++;}
614 } else {
615 if( ! fixParam[n] ) { fixParam[n]=1; mNParFree--;}
616 }
617 stepParam(n) = step;
618 if(debugLevel) {cout<<"Set_Step"; PrintParm(n);}
619}
620
621/*!
622 Definition du pas minimum `val' pour le parametre `i'
623 pouvant etre utilise dans le calcul automatique des derivees
624 (soit de la fonction, soit du Xi2 selon les parametres du fit).
625 Si nul pas de limite, si negatif alors `EPS(i)' (cf SetEps).
626 Inutile dans le cas ou les derivees sont donnees
627 par l'utilisateur.
628*/
629void GeneralFit::SetMinStepDeriv(int i,double val)
630{
631 ASSERT(i>=0 && i<mNPar);
632 if(val<0.) minStepDeriv(i) = Eps(i);
633 else minStepDeriv(i) = val;
634 if(debugLevel>0) cout<<"SetMinStepDeriv("<<i<<") = "<<minStepDeriv(i)<<endl;
635}
636
637/*!
638 Definition du pas minimum `val' pour tout les parametres
639 (voir description SetMinStepDeriv ci-dessus).
640*/
641void GeneralFit::SetMinStepDeriv(double val)
642{
643 if(debugLevel>0) cout<<"SetMinStepDeriv "<<val<<endl;
644 for(int i=0;i<mNPar;i++) SetMinStepDeriv(i,val);
645}
646
647//////////////////////////////////////////////////////////////////////
648/*!
649 Definition des bornes du parametre "n"
650 Si max<=min, parametre non-borne.
651*/
652void GeneralFit::SetBound(int n, double min, double max)
653{
654 ASSERT(n>=0 && n<mNPar && max>min);
655
656 minParam(n) = min;
657 maxParam(n) = max;
658 if( ! boundParam[n] ) {
659 boundParam[n] = 1;
660 mNParBound++;
661 if(debugLevel>0)
662 cout<<"SetBound "<<n<<" min="<<min<<" max="<<max
663 <<" (Nbound="<<mNParBound<<")"<<endl;
664 }
665}
666
667/*!
668 Pour re-borner le parametre "n" aux bornes par defaut
669*/
670void GeneralFit::SetBound(int n)
671{
672 ASSERT(n>=0 && n<mNPar && maxParam(n)>minParam(n));
673 SetBound(n,minParam(n),maxParam(n));
674}
675
676/*!
677 Pour ne plus borner le parametre "n"
678*/
679void GeneralFit::SetUnBound(int n)
680{
681 ASSERT(n>=0 && n<mNPar);
682
683 if( boundParam[n] ) {
684 boundParam[n] = 0;
685 mNParBound--;
686 if(debugLevel>0) cout<<" SetUnBound "<<n
687 <<" (Nbound="<<mNParBound<<")"<<endl;
688 }
689}
690
691/*!
692 Pour ne plus borner tous les parametres
693*/
694void GeneralFit::SetUnBound()
695{
696 for(int i=0;i<mNPar;i++) SetUnBound(i);
697}
698
699//////////////////////////////////////////////////////////////////////
700/*!
701 Pour fixer le parametre "n" a la valeur "v"
702*/
703void GeneralFit::SetFix(int n,double v)
704{
705 ASSERT(n>=0 && n<mNPar);
706
707 Param(n) = v;
708 if( ! fixParam[n] ) {
709 fixParam[n] = 1;
710 mNParFree--;
711 }
712 if(debugLevel>0) cout<<" SetFix "<<n
713 <<" v="<<v
714 <<" (Nfree="<<mNParFree
715 <<")"<<endl;
716}
717
718/*!
719 Pour fixer le parametre "n" a la valeur par defaut
720*/
721void GeneralFit::SetFix(int n)
722{
723 ASSERT(n>=0 && n<mNPar);
724 SetFix(n,Param(n));
725}
726
727/*!
728 Pour liberer le parametre "n"
729*/
730void GeneralFit::SetFree(int n)
731{
732 ASSERT(n>=0 && n<mNPar);
733
734 if( fixParam[n] ) {
735 fixParam[n] = 0;
736 mNParFree++;
737 if(debugLevel>0) cout<<" SetFree "<<n
738 <<" Step "<<stepParam(n)
739 <<" (Nfree="<<mNParFree<<")"<<endl;
740 if(stepParam(n)<=0.)
741 cout<<"ATTENTION SetFree["<<n<<"] avec step<=0 "
742 <<stepParam(n)<<endl;
743 }
744}
745
746/*!
747 Pour liberer tous les parametres
748*/
749void GeneralFit::SetFree()
750{
751 for(int i=0;i<mNPar;i++) SetFree(i);
752}
753
754//////////////////////////////////////////////////////////////////////
755/*!
756 Retourne la valeur du parametre "n"
757*/
758double GeneralFit::GetParm(int n)
759{
760 ASSERT(n>=0 && n<mNPar);
761 return Param(n);
762}
763
764/*!
765 Retourne les valeurs des parametres dans un vecteur.
766*/
767Vector GeneralFit::GetParm()
768{
769return Param;
770}
771
772/*!
773 Retourne la valeur de l'erreur du parametre "n"
774*/
775double GeneralFit::GetParmErr(int n)
776{
777 ASSERT(n>=0 && n<mNPar);
778 return errParam(n);
779}
780
781/*!
782 Retourne la covariance pour les parametre `i' et `j'
783*/
784double GeneralFit::GetCoVar(int i,int j)
785{
786 ASSERT(i>=0 && i<mNPar && j>=0 && j<mNPar);
787 return ATGA(i,j);
788}
789
790//////////////////////////////////////////////////////////////////////
791/*!
792 Retourne la valeur du pas du parametre "n"
793*/
794double GeneralFit::GetStep(int n)
795{
796 ASSERT(n>=0 && n<mNPar);
797 return stepParam(n);
798}
799
800/*!
801 Retourne la valeur de la borne superieure du parametre "n"
802*/
803double GeneralFit::GetMax(int n)
804{
805 ASSERT(n>=0 && n<mNPar);
806 return maxParam(n);
807}
808
809/*!
810 Retourne la valeur de la borne inferieure du parametre "n"
811*/
812double GeneralFit::GetMin(int n)
813{
814 ASSERT(n>=0 && n<mNPar);
815 return minParam(n);
816}
817
818//////////////////////////////////////////////////////////////////////
819/*!
820 Impression du status du fit
821*/
822void GeneralFit::PrintStatus()
823{
824 cout<<"GeneralFit::PrintStatus"
825 <<" mData="<<mData
826 <<" mFunction="<<mFunction
827 <<" mFuncXi2="<<mFuncXi2
828 <<endl;
829 cout<<" mNVar="<<mNVar
830 <<" mNPar="<<mNPar
831 <<" mNParFree="<<mNParFree
832 <<" mNParBound="<<mNParBound
833 <<endl;
834 cout<<" Lambda_Fac="<<Lambda_Fac
835 <<" stopChi2="<<stopChi2
836 <<" maxStep="<<maxStep
837 <<" nStopMx="<<nStopMx<<" stopChi2SMx="<<stopChi2SMx
838 <<" nStopLent="<<nStopLent
839 <<" debugLevel="<<debugLevel
840 <<endl;
841 PrintParm();
842}
843
844/*!
845 Impression des resultats du fit
846*/
847void GeneralFit::PrintFit()
848{
849 cout<<"PrintFit: Chi2="<<Chi2
850 <<" Lambda="<<Lambda
851 <<" nStep="<<nStep
852 <<" nStop="<<nStop
853 <<" nStopL="<<nStopL
854 <<" nDDL="<<mNddl
855 <<endl;
856 PrintParm();
857}
858
859/*!
860 Impression des informations relatives au parametre "n"
861*/
862void GeneralFit::PrintParm(int n)
863{
864 ASSERT(n>=0 && n<mNPar);
865
866 cout<<"Par["<<n<<"] "<<nameParam[n]
867 <<" F"<<fixParam[n]
868 <<" B"<<boundParam[n]
869 <<" : "<<Param(n)
870 <<" +/- "<<errParam(n)
871 <<" : "<<stepParam(n)
872 <<" "<<minParam(n)
873 <<" "<<maxParam(n)
874 <<" : "<<Eps(n)
875 <<" "<<minStepDeriv(n)
876 <<endl;
877}
878
879/*!
880 Impression des informations relatives a tous les parametres
881*/
882void GeneralFit::PrintParm()
883{
884 cout<<"*** Parametres : fix bnd : par err : step min max : eps dmin\n";
885 for (int i=0; i<mNPar; i++) PrintParm(i);
886 cout<<endl;
887}
888
889//////////////////////////////////////////////////////////////////////
890/*!
891 Methode de fit.
892 \anchor GeneralFit_Fit
893 \verbatim
894 Fonction de fit de la fonction f(x,y,z,...:p1,p2,...,pn)
895 sur les donnees x[i],y[i],z[i],...,F[i],ErrF[i]
896 - Methode: fit des moindres carres dans le cas non lineaire
897 - Reference: Statistical and Computational Methods in Data Analysis
898 Siegmund Brandt, North-Holland 1970 p 204-206.
899 Introduction des limites pour la variation des parametres (cmv).
900 Increment des parametres selon la methode de Levenberg-Marquardt
901 (Numerical Recipes in C, chap 15 Modeling of Data, Nonlinear Models,
902 Levenberg-Marquardt Method p683)
903 - Gestion des parametres bornes:
904 si p est un parametre borne entre pmin et pmax, le parametre fitte est q
905 tel que q = tang((p-C)/D) .... p = C + D*atan(q)
906 ou C = (pmin+pmax)/2. et D = (pmax-pmin)/Pi
907 On a dq = (1+q**2)/D * dp .... dp = D/(1+q**2) * dq
908 et dF/dq = dF/dp * dp/dq = D/(1+q**2) * dF/dp
909 dF/dp = dF/dq * dq/dp = (1+q**2)/D * dF/dp
910 ^ q
911 | | *| "tang()"
912 | | *|
913 | | *|
914 | | * |
915 | | * |
916 | | * |
917 | | * |
918 Pmin| C| * |Pmax
919 --------------|---------------*---------------|--------------> p
920 -Pi/2| * |0 |Pi/2
921 | * | |
922 | * | |
923 | * | |
924 | * | |
925 |* | |
926 |* | |
927 |* | |
928 <------------------- D --------->
929
930 - Criteres de convergence, arrets standards:
931 - SOIT: le Chi2 est descendu de moins de stopChi2
932 entre l'iteration n et n+1
933 (stopChi2 est change par SetStopChi2)
934 - SOIT: 1. le chi2 est remonte de moins de stopChi2SMx et
935 2. les parametres libres ont varie de moins de Eps(i)
936 pendant les nStopmx dernieres iterations
937 Si nStopmx<=0, alors ce critere n'est pas applique (def=3).
938 (nStopmx,stopChi2SMx sont changes par SetStopMx, Eps par SetEps)
939
940 - Criteres de convergence, arrets par non-convergence:
941 - plus de "maxStep" iterations.
942
943 - Criteres de convergence, arrets speciaux:
944 - Si l'utilisateur a demande explicitement la methode d'arret
945 "SetStopLent()", arret si :
946 1. le Chi2 est descendu et
947 2. les parametres libres ont varies de moins de Eps
948 pendant les nStopLent dernieres iterations.
949 (nStopLent est change par SetStopLent, Eps par SetEps)
950
951 - Remarques diverses:
952 Les points avec erreurs <=0 ne sont pas utilises dans le fit.
953 Les bornes des parametres ne peuvent etre atteintes
954 - entrees:
955 la fonction est definie par une classe GeneralFunction
956 les donnees sont passees par une classe GeneralFitData
957 le nombre de parametres et le nombre de variables doivent etre
958 coherents entre GeneralFunction GeneralFitData GeneralFit
959 - Return:
960 la function elle meme retourne le nombre d'iterations du fit si succes
961 -1 : si le nombre de degre de liberte est <0
962 -10 : si l'inversion de la matrice des erreurs n'a pas ete possible
963 -11 : si un element diagonal de la matrice des covariances est <=0
964 -20 : si le fit n'a pas converge (nstep>nNstepMX)
965 -100-N : si le parametre "N" est initialise hors limites
966 -200-N : si le parametre "N" atteint sa limite inferieure
967 -300-N : si le parametre "N" atteint sa limite superieure
968 \endverbatim
969*/
970int GeneralFit::Fit()
971{
972 volatile double oldChi2;
973 Matrix COVAR(mNPar,mNPar);
974 Vector DA(mNPar);
975 Vector dparam(mNPar);
976 Vector paramTry(mNPar);
977 Vector param_tr(mNPar);
978 Vector paramTry_tr(mNPar);
979 Vector step_tr(mNPar);
980 nStop = nStopL = nStep = 0;
981 Chi2 = oldChi2 = 0.;
982 Lambda = 0.001;
983 mNddl = mData->NDataGood() - mNParFree;
984 if(mNddl<0) return -1;
985 mNtry++;
986
987 if(debugLevel>= 2)
988 cout<<"\n********* DEBUT GENERALFIT.FIT() **************"<<endl;
989
990 // set matrices C,D dans le cas de parametres bornes
991 if(mNParBound>0) Set_Bound_C_D();
992
993 if(debugLevel>= 2) PrintStatus();
994
995 // check de la coherence des operations et assignations
996 CheckSanity();
997
998 // Pour les parametres bornes on verifie
999 // qu'ils sont initialises dans leurs limites
1000 {for(int i=0;i<mNPar;i++) {
1001 if( !boundParam[i] || fixParam[i] ) continue;
1002 if( minParam(i)<Param(i) && Param(i)<maxParam(i) ) continue;
1003 /* if(debugLevel>= 1) */
1004 cout<<"Parametre "<<i<<" initialise hors limites "
1005 <<minParam(i)<<" < "<<Param(i)
1006 <<" < "<<maxParam(i)<<endl;
1007 return(-100-i);
1008 }}
1009
1010 // premier essai d'initialisation
1011 param_tr = p_vers_tr(Param);
1012 dparam = stepParam / 2.;
1013 put_in_limits_for_deriv(Param,dparam);
1014 if(mFunction!=NULL) mFunction->SetDeltaParm(dparam.Data());
1015 else if(mFuncXi2!=NULL) mFuncXi2->SetDeltaParm(dparam.Data());
1016 step_tr = dp_vers_dtr(stepParam,param_tr);
1017
1018 if(debugLevel>= 2) {
1019 cout<<"ESSAI numero 1: Param:"<<endl;
1020 cout<<Param;
1021 cout<<"param_tr:"<<endl;
1022 cout<<param_tr;
1023 cout<<"step_tr:"<<endl;
1024 cout<<step_tr;
1025 }
1026 if(mFunction!=NULL) TryFunc(Param,param_tr);
1027 else if(mFuncXi2!=NULL) TryXi2(Param,param_tr);
1028 ATGA = ATGA_Try;
1029 BETA = BETA_Try;
1030 oldChi2 = Chi2;
1031
1032 // Iterations
1033 while (1) {
1034 nStep++;
1035
1036 // un nouvel essai (si Lambda!=0)
1037 {for(int i=0; i<mNPar; i++)
1038 if(! fixParam[i] ) ATGA(i,i) *= 1 + Lambda;
1039 else ATGA(i,i) = 1.;}
1040
1041 // Calcul de la matrice des covariances
1042#ifdef __mac__
1043 COVAR = SimpleMatrixOperation<r_8>::Inverse(ATGA); /* $CHECK$ Reza 10/3/2000 */
1044#else
1045 TRY {
1046 COVAR = SimpleMatrixOperation<r_8>::Inverse(ATGA); /* $CHECK$ Reza 10/3/2000 */
1047 } CATCHALL {
1048 if(debugLevel>0) {
1049 cout<<"Pb inversion matrice ATGA:"<<endl;
1050 cout<<ATGA;
1051 }
1052 return(-10);
1053 } ENDTRY
1054#endif
1055
1056 if (debugLevel >= 3) {
1057 cout<<"Matrice (tA G A)^-1 = \n";
1058 cout<<COVAR;
1059 }
1060
1061 // calculs des deplacements a effectuer
1062 DA = COVAR * BETA;
1063 if (debugLevel >=2) {
1064 cout<<"Correction parametres DA : \n";
1065 cout<<DA;
1066 }
1067
1068
1069 //////////////////////////////////////////////////
1070 ////////////////// Arret du Fit //////////////////
1071 // si Lambda = 0, le fit a converge on s'arrete
1072 // ou bien on a trop d'iterations
1073 //////////////////////////////////////////////////
1074 if(Lambda == 0 || nStep > maxStep) {
1075 // trop d'iterations
1076 if(nStep>maxStep)
1077 cout<<"GeneralFit : pas de convergence"<<endl;
1078 // Probleme de matrice de covariance non-definie positive?
1079 bool bad_covar = false;
1080 {for(int i=0; i<mNPar; i++) {
1081 if( fixParam[i] ) errParam(i) = 0.;
1082 else {
1083 stepParam(i) = DA(i);
1084 if( COVAR(i,i)<=0. ) {
1085 if( debugLevel>0 )
1086 cout<<"Erreur: Par["<<i<<"]="<<param_tr(i)
1087 <<" ("<<Param(i)<<") COVAR()="<<COVAR(i,i)
1088 <<" step="<<DA(i)<<endl;
1089 errParam(i) = 0.;
1090 bad_covar = true;
1091 } else {
1092 errParam(i) = sqrt( COVAR(i,i) );
1093 }
1094 }
1095 }}
1096 // print de debug pour parametres bornes
1097 if(debugLevel>= 2) {
1098 cout<<"param_tr:"<<endl;
1099 cout<<param_tr;
1100 cout<<"stepParam_tr:"<<endl;
1101 cout<<stepParam;
1102 cout<<"errParam_tr:"<<endl;
1103 cout<<errParam;
1104 }
1105 // Calcul de la matrice des covariances
1106 {for(int i=0; i<mNPar; i++) {
1107 for(int j=0; j<mNPar; j++) {
1108 if( fixParam[i] || fixParam[j] ) {
1109 // Parametre fixe, on retourne l'identite
1110 if(i==j) ATGA(i,j) = 1.; else ATGA(i,j) = 0.;
1111 } else if( errParam(i)<=0. || errParam(j)<=0.) {
1112 // parametres avec mauvaise variance, on retourne 0
1113 ATGA(i,j) = 0;
1114 } else {
1115 // parametres OK
1116 ATGA(i,j) = COVAR(i,j)/(errParam(i)*errParam(j));
1117 }
1118 }
1119 }}
1120 if (debugLevel >= 1) {
1121 cout<<">>> Matrice des Covariances = \n";
1122 cout<<ATGA;
1123 }
1124 // Calcul du step et de l'erreur finale en tenant
1125 // compte des parametres bornes
1126 stepParam = dtr_vers_dp(stepParam,param_tr);
1127 errParam = dtr_vers_dp(errParam,param_tr);
1128 // Print si demande et code de retour.
1129 if (debugLevel>0 ) PrintFit();
1130 if(nStep>maxStep) return(-20);
1131 else if(bad_covar) return(-11);
1132 else return(nStep);
1133 }
1134 ////////////////////////////////////////////////////////
1135 ////////////////// Fin d'Arret du Fit //////////////////
1136 ////////////////////////////////////////////////////////
1137
1138 // Gestion des deplacements
1139 {for (int i=0; i<mNPar; i++) {
1140 if( fixParam[i] ) { DA(i) = 0; continue;}
1141 // le premier deplacement ne peut etre plus grand que stepParam
1142 if( nStep == 1 && fabs(DA(i)) > step_tr(i) ) {
1143 DA(i) = DA(i) < 0. ? -step_tr(i) : step_tr(i);
1144 if(debugLevel>1 ) cout<<"Excursion parametre "<<i
1145 <<" limitee a "<<DA(i)<<endl;
1146 }
1147 }}
1148 paramTry_tr = param_tr + DA;
1149 paramTry = tr_vers_p(paramTry_tr);
1150 dparam = dtr_vers_dp(DA,paramTry_tr);
1151 dparam /= 2.;
1152 put_in_limits_for_deriv(paramTry,dparam);
1153 {for(int i=0; i<mNPar; i++) {
1154 if( ! boundParam[i] ) continue;
1155 if(paramTry(i) <= minParam(i)) {
1156 if(debugLevel>0) cout<<"Parametre "<<i
1157 <<" limite au minimum"<<endl;
1158 Param(i) = minParam(i);
1159 return(-200-i);
1160 } else if (paramTry(i) >= maxParam(i)) {
1161 if(debugLevel>0) cout<<"Parametre "<<i
1162 <<" limite au maximum"<<endl;
1163 Param(i) = maxParam(i);
1164 return(-300-i);
1165 }
1166 }}
1167
1168 // Nouvel essai
1169 if(mFunction!=NULL) mFunction->SetDeltaParm(dparam.Data());
1170 else if(mFuncXi2!=NULL) mFuncXi2->SetDeltaParm(dparam.Data());
1171 if(debugLevel >= 2) {
1172 cout<<">>>>>>>>>>> ESSAI avec nouveaux parametres\n";
1173 cout<<"paramTry:\n";
1174 cout<<paramTry;
1175 cout<<"paramTry_tr:\n";
1176 cout<<paramTry_tr;
1177 cout<<"dparam:\n";
1178 cout<<dparam;
1179 }
1180 if(mFunction!=NULL) TryFunc(paramTry,paramTry_tr);
1181 else if(mFuncXi2!=NULL) TryXi2(paramTry,paramTry_tr);
1182
1183 if (debugLevel >= 2)
1184 cout<<"step "<<nStep<<" Chi2 : old="<<oldChi2
1185 <<" new="<<Chi2<<" d="<<Chi2-oldChi2<<endl;
1186 if(FileStep) write_in_step(Chi2,paramTry);
1187
1188 // *************************************************************
1189 // ****************** quelle strategie sur Lambda ???? *********
1190 // *************************************************************
1191 if (Chi2 < oldChi2) {
1192 // ****************** le Chi2 est descendu ******************
1193 nStop = 0;
1194 if(nStopLent>0) {
1195 // Arret special demande, comment se comporte les parametres?
1196 int k=0;
1197 for (int i=0; i<mNPar; i++) if( (!fixParam[i]) &&
1198 (fabs(param_tr(i)-paramTry_tr(i))<Eps(i))) k++;
1199 if (k==mNParFree) nStopL++; // Tous les parametres ont peu varies
1200 else nStopL=0;
1201 if (debugLevel>=2) cout<<k<<" parametres sur "<<mNParFree
1202 <<" ont peu varies, nStopL="<<nStopL<<endl;
1203 } else nStopL = 0;
1204 // Preparation des parametres pour iteration suivante
1205 ATGA = ATGA_Try;
1206 BETA = BETA_Try;
1207 param_tr = paramTry_tr;
1208 Param = paramTry;
1209 Lambda *= 1./Lambda_Fac;
1210 // Arret ?
1211 if (oldChi2-Chi2<stopChi2) {
1212 // arret normal, convergence
1213 Lambda = 0;
1214 if (debugLevel >= 2)
1215 cout<<"Arret>> demande car Chi2 decroit et oldChi2-Chi2= "
1216 <<oldChi2-Chi2<<"<"<<stopChi2<<endl;
1217 } else if (nStopLent>0 && nStopL >= nStopLent) {
1218 // arret demande par SetStopLent, variation lente des parametres
1219 Lambda = 0.;
1220 if (debugLevel >= 2)
1221 cout<<"Arret>> demande car Chi2 decroit et nStop(lent)= "
1222 <<nStopL<<">="<<nStopLent<<endl;
1223 }
1224 oldChi2 = Chi2;
1225 if (debugLevel >= 2) cout<<"Succes essai: Lambda divided by "
1226 <<Lambda_Fac<<" -> "<<Lambda<<endl;
1227 } else {
1228 // ****************** le Chi2 est remonte ******************
1229 nStopL = 0;
1230 if(nStopMx>0 && Chi2-oldChi2<stopChi2SMx) {
1231 // Il est remonte tres peu, comment se comporte les parametres?
1232 int k=0;
1233 for (int i=0; i<mNPar; i++) if( (!fixParam[i]) &&
1234 (fabs(param_tr(i)-paramTry_tr(i))<Eps(i))) k++;
1235 if (k==mNParFree) nStop++; // Tous les parametres ont peu varies
1236 else nStop=0;
1237 if (debugLevel>=2) cout<<k<<" parametres sur "<<mNParFree
1238 <<" ont peu varies, nStop="<<nStop<<endl;
1239 } else nStop = 0;
1240 // Preparation des parametres pour iteration suivante
1241 Lambda *= Lambda_Fac;
1242 // Arret ?
1243 if (nStopMx>0 && nStop>=nStopMx) {
1244 // arret normal, convergence car ci2 varie peu et parametres aussi
1245 Lambda = 0.;
1246 if (debugLevel >= 2)
1247 cout<<"Arret>> demande car Chi2 croit et nstop= "
1248 <<nStop<<">="<<nStopMx<<endl;
1249 }
1250 Chi2 = oldChi2;
1251 if (debugLevel >= 2)
1252 cout<<"Echec essai: Lambda multiplied by "<<Lambda_Fac
1253 <<" -> "<<Lambda<<" nStop="<<nStop<<endl;
1254 }
1255
1256 } // fin des iterations
1257}
1258
1259//////////////////////////////////////////////////////////////////////
1260/*!
1261 Recalcul du Chi2 a partir des parametres courants (`par==NULL')
1262 ou a partir du tableau de parametres `par'.
1263 Retourne le chi2 et le nombre de degres de liberte.
1264 Si nddl<0 probleme.
1265*/
1266double GeneralFit::ReCalChi2(int& nddl, double *par)
1267{
1268double c2 = -1.;
1269if(par==NULL) par = Param.Data();
1270if( mData->NData() <= 0 ) {nddl = -100; return 0.;}
1271
1272if( mFunction != NULL ) {
1273
1274 double e,result;
1275
1276 nddl = 0; c2 = 0.;
1277 for(int k=0; k<mData->NData(); k++) {
1278 if (! mData->mOK[k]) continue;
1279 e = mData->mErr[k];
1280 result = mFunction->Value(&mData->mXP[mNVar*k],par);
1281 c2 += (mData->mF[k]-result)*(mData->mF[k]-result)/(e*e);
1282 nddl++;
1283 }
1284 nddl -= mNParFree;
1285
1286 return c2;
1287
1288} else if( mFuncXi2 != NULL ) {
1289
1290 c2 = mFuncXi2->Value(*mData,par,nddl);
1291 nddl -= mNParFree;
1292 return c2;
1293
1294} else {
1295
1296 cout<<"GeneralFit::ReCalChi2_Erreur: mFunction && mFuncXi2 == NULL"<<endl;
1297 nddl = -1;
1298 return c2;
1299}
1300
1301}
1302
1303//////////////////////////////////////////////////////////////////////
1304/*!
1305 Retourne une structure ``GeneralFitData'' contenant
1306 les residus du fit (val-func) pour les points du fit.
1307 Si ``clean'' est ``true''
1308 seules les donnees valides de ``data'' sont copiees.
1309 Si ``clean'' est ``false'' (defaut) toutes les donnees
1310 sont copiees et la taille totale de ``data'' est allouee
1311 meme si elle est plus grande que la taille des donnees stoquees.
1312*/
1313GeneralFitData GeneralFit::DataResidus(bool clean)
1314{
1315if(!mData || !mFunction)
1316 throw(NullPtrError("GeneralFit::DataResidus: NULL pointer\n"));
1317GeneralFitData datres(*mData,clean);
1318for(int k=0; k<mData->NData(); k++)
1319 datres.mF[k] -= mFunction->Value(&datres.mXP[mNVar*k],Param.Data());
1320return datres;
1321}
1322
1323//////////////////////////////////////////////////////////////////////
1324/*!
1325 Retourne une structure ``GeneralFitData'' contenant
1326 les valeurs de la fonction fittee pour les points du fit.
1327 (voir commentaires pour ``clean'' dans ``DataResidus'')
1328*/
1329GeneralFitData GeneralFit::DataFunction(bool clean)
1330{
1331if(!mData || !mFunction)
1332 throw(NullPtrError("GeneralFit::DataFunction: NULL pointer\n"));
1333GeneralFitData datres(*mData,clean);
1334for(int k=0; k<mData->NData(); k++)
1335 datres.mF[k] = mFunction->Value(&datres.mXP[mNVar*k],Param.Data());
1336return datres;
1337}
1338
1339//////////////////////////////////////////////////////////////////////
1340/*!
1341 Imprime le commentaire lie a l'erreur rc retournee par Fit()
1342 (voir le commentaire de la methode `Fit()')
1343*/
1344void GeneralFit::PrintFitErr(int rc)
1345{
1346int n;
1347if(rc>0) return;
1348
1349if(rc==-1)
1350 cout<<"rc = "<<rc<<" : le nombre de degre de liberte est <0"<<endl;
1351
1352else if(rc==-10)
1353 cout<<"rc = "<<rc<<" : l'inversion de la matrice des erreurs n'a pas ete possible"<<endl;
1354
1355else if(rc==-11)
1356 cout<<"rc = "<<rc<<" : un element diagonal de la matrice des covariances est <=0"<<endl;
1357
1358else if(rc==-20)
1359 cout<<"rc = "<<rc<<" : le fit n'a pas converge (nstep>nNstepMX="<<maxStep<<")"<<endl;
1360
1361else if(rc>-200 && rc<=-100) {
1362 n = -100-rc;
1363 cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
1364 <<") est initialise hors limites"<<endl;
1365}
1366
1367else if(rc>-300 && rc<=-200) {
1368 n = -200-rc;
1369 cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
1370 <<") atteint sa limite inferieure"<<endl;
1371}
1372
1373else if(rc>-400 && rc<=-300) {
1374 n = -300-rc;
1375 cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
1376 <<") atteint sa limite superieure"<<endl;
1377}
1378
1379else cout<<"rc = "<<rc<<" : type d'erreur inconnue"<<endl;
1380
1381}
1382
1383//////////////////////////////////////////////////////////////////////
1384// Fonctions privees
1385//////////////////////////////////////////////////////////////////////
1386
1387//////////////////////////////////////////////////////////////////////
1388void GeneralFit::write_in_step(double ci2,Vector& par)
1389{
1390if(FileStep==NULL) return;
1391fprintf(FileStep,"%d %d %f",mNtry,nStep,ci2);
1392for(int i=0; i<mNPar; i++) fprintf(FileStep," %f",par(i));
1393fprintf(FileStep,"\n");
1394}
1395
1396//////////////////////////////////////////////////////////////////////
1397void GeneralFit::TryFunc(Vector& par,Vector& par_tr)
1398{
1399 BETA_Try = 0;
1400 ATGA_Try = 0;
1401 Chi2 = 0;
1402 Vector deriv(mNPar);
1403 Vector derivtr(mNPar);
1404 double result;
1405
1406 for(int k=0; k<mData->NData(); k++) {
1407 if (! mData->mOK[k]) continue;
1408 double e = mData->mErr[k];
1409 if(mNParBound==0)
1410 result = mFunction->Val_Der(&mData->mXP[mNVar*k]
1411 ,par.Data(),derivtr.Data());
1412 else {
1413 result = mFunction->Val_Der(&mData->mXP[mNVar*k]
1414 ,par.Data(),deriv.Data());
1415 dtr_vers_dp(deriv,par_tr,derivtr);
1416 }
1417 double Gkk = 1/(e*e);
1418 double Ck = mData->mF[k] - result;
1419 Chi2 += Ck*Ck*Gkk;
1420 for(int j=0; j<mNPar; j++) {
1421 if( fixParam[j] ) continue;
1422 for(int i=0; i<mNPar; i++)
1423 if(!fixParam[i]) ATGA_Try(i,j) += derivtr(i)*Gkk*derivtr(j);
1424 BETA_Try(j) += derivtr(j) * Gkk * Ck;
1425 }
1426 }
1427
1428 if (debugLevel >= 3) {
1429 cout<<"Try: matrice ( At * G * A )_Try\n";
1430 cout<<ATGA_Try;
1431 cout<<"Try: beta_Try:\n";
1432 cout<<BETA_Try;
1433 }
1434}
1435
1436//////////////////////////////////////////////////////////////////////
1437void GeneralFit::TryXi2(Vector& par,Vector& par_tr)
1438{
1439 double c, *parloc;
1440 BETA_Try = 0;
1441 ATGA_Try = 0;
1442 Chi2 = 0;
1443
1444 parloc = par.Data(); // He oui, encore ces ... de const*
1445 Chi2 = mFuncXi2->Value(*mData,parloc,mNddl);
1446 mNddl -= mNParFree;
1447
1448 // Calcul des derivees du Xi2 (vecteur du gradient)
1449 {for(int i=0;i<mNPar; i++) {
1450 if( fixParam[i] ) continue;
1451 c = c_dtr_vers_dp(i,par_tr(i));
1452 BETA_Try(i) = -0.5 * mFuncXi2->Derivee(*mData,i,parloc) * c;
1453 }}
1454
1455 // Calcul des derivees 2sd du Xi2 (matrice de courbure ou 0.5*Hessien)
1456 double c1,c2;
1457 {for(int i=0;i<mNPar; i++) {
1458 if( fixParam[i] ) continue;
1459 c1 = c_dtr_vers_dp(i,par_tr(i));
1460 for(int j=0;j<mNPar; j++) {
1461 if( fixParam[j] ) continue;
1462 c2 = c_dtr_vers_dp(j,par_tr(j));
1463 ATGA_Try(i,j) = 0.5 * mFuncXi2->Derivee2(*mData,i,j,parloc) *c1*c2;
1464 }
1465 }}
1466 // et on symetrise car d/di(dC2/dj) = d/dj(dC2/di) mathematiquement
1467 // mais malheureusement pas numeriquement.
1468 if( mNPar>1) {
1469 for(int i=0;i<mNPar-1; i++) {
1470 if( fixParam[i] ) continue;
1471 for(int j=i+1;j<mNPar; j++) {
1472 if( fixParam[j] ) continue;
1473 c1 = 0.5*(ATGA_Try(i,j) + ATGA_Try(j,i));
1474 ATGA_Try(i,j) = c1;
1475 ATGA_Try(j,i) = c1;
1476 }
1477 }
1478 }
1479
1480 if (debugLevel >= 3) {
1481 cout<<"Try: matrice ( At * G * A )_Try\n";
1482 cout<<ATGA_Try;
1483 cout<<"Try: beta_Try:\n";
1484 cout<<BETA_Try;
1485 }
1486}
1487
1488//////////////////////////////////////////////////////////////////////
1489void GeneralFit::CheckSanity()
1490{
1491 ASSERT( mData != NULL );
1492 ASSERT( mFunction != NULL || mFuncXi2 != NULL );
1493 if( mFunction != NULL ) {
1494 ASSERT( mFunction->NVar() == mNVar );
1495 ASSERT( mData->NVar() == mNVar );
1496 }
1497 ASSERT( mNParFree > 0 && mNParFree <= mNPar );
1498 ASSERT( mNParBound >= 0 && mNParBound <= mNPar );
1499 ASSERT( mNParFree <= mData->NDataGood() );
1500}
1501
1502//////////////////////////////////////////////////////////////////////
1503/*!
1504 \verbatim
1505 C = (min+max)/2
1506 D = (max-min)/Pi
1507 \endverbatim
1508*/
1509void GeneralFit::Set_Bound_C_D(int i)
1510{
1511 // ASSERT(i>=0 && i<mNPar);
1512 C(i) = D(i) = 0.;
1513 if( !boundParam[i] || fixParam[i] ) return;
1514 C(i) = (maxParam(i)+minParam(i))/2.;
1515 D(i) = (maxParam(i)-minParam(i))/M_PI;
1516}
1517
1518//////////////////////////////////////////////////////////////////////
1519void GeneralFit::Set_Bound_C_D()
1520{
1521 for(int i=0;i<mNPar;i++) Set_Bound_C_D(i);
1522 if(debugLevel>= 2) {
1523 cout<<"Set_Bound_C_D: C=\n";
1524 cout<<C;
1525 cout<<"Set_Bound_C_D: D=\n";
1526 cout<<D;
1527 }
1528}
1529
1530//////////////////////////////////////////////////////////////////////
1531/*!
1532 \verbatim
1533 tr = tan( (p-C)/D )
1534 \endverbatim
1535*/
1536double GeneralFit::p_vers_tr(int i,double p)
1537{
1538 // ASSERT(i>=0 && i<mNPar);
1539 double tr = p;
1540 if(boundParam[i]) tr = tan((p-C(i))/D(i));
1541 return(tr);
1542}
1543
1544//////////////////////////////////////////////////////////////////////
1545Vector GeneralFit::p_vers_tr(Vector const& p)
1546{
1547 Vector tr(p);
1548 for(int i=0;i<mNPar;i++) {
1549 if( fixParam[i] || ! boundParam[i] ) continue;
1550 tr(i) = p_vers_tr(i,p(i));
1551 }
1552 return(tr);
1553}
1554
1555//////////////////////////////////////////////////////////////////////
1556void GeneralFit::p_vers_tr(Vector const& p,Vector& tr)
1557{
1558 for(int i=0;i<mNPar;i++) {
1559 if( fixParam[i] ) continue;
1560 if( ! boundParam[i] ) tr(i) = p(i);
1561 else tr(i) = tan((p(i)-C(i))/D(i));
1562 }
1563}
1564
1565//////////////////////////////////////////////////////////////////////
1566/*!
1567 \verbatim
1568 p = C+D*atan(tr)
1569 \endverbatim
1570*/
1571double GeneralFit::tr_vers_p(int i,double tr)
1572{
1573 // ASSERT(i>=0 && i<mNPar);
1574 double p = tr;
1575 if(boundParam[i]) p = C(i)+D(i)*atan(tr);
1576 return(p);
1577}
1578
1579//////////////////////////////////////////////////////////////////////
1580Vector GeneralFit::tr_vers_p(Vector const& tr)
1581{
1582 Vector p(tr);
1583 for(int i=0;i<mNPar;i++) {
1584 if( fixParam[i] || ! boundParam[i] ) continue;
1585 p(i) = tr_vers_p(i,tr(i));
1586 }
1587 return(p);
1588}
1589
1590//////////////////////////////////////////////////////////////////////
1591void GeneralFit::tr_vers_p(Vector const& tr,Vector& p)
1592{
1593 for(int i=0;i<mNPar;i++) {
1594 if( fixParam[i] ) continue;
1595 if( ! boundParam[i] ) p(i) = tr(i);
1596 else p(i) = C(i)+D(i)*atan(tr(i));
1597 }
1598}
1599
1600//////////////////////////////////////////////////////////////////////
1601/*!
1602 \verbatim
1603 dtr = (1+tr**2)/D * dp = (1+tan( (p-C)/D )**2)/D * dp = coeff * dp
1604 attention: df/dp = (1+tr**2)/D * dF/dtr = coeff * dF/dtr
1605 \endverbatim
1606*/
1607double GeneralFit::c_dp_vers_dtr(int i,double tr)
1608{
1609 // ASSERT(i>=0 && i<mNPar);
1610 double coeff = 1.;
1611 if(boundParam[i]) coeff = (1.+tr*tr)/D(i);
1612 return(coeff);
1613}
1614
1615//////////////////////////////////////////////////////////////////////
1616Vector GeneralFit::dp_vers_dtr(Vector const& dp,Vector const& tr)
1617{
1618 Vector dtr(dp);
1619 for(int i=0;i<mNPar;i++) {
1620 if( fixParam[i] || ! boundParam[i] ) continue;
1621 dtr(i) *= c_dp_vers_dtr(i,tr(i));
1622 }
1623 return(dtr);
1624}
1625
1626//////////////////////////////////////////////////////////////////////
1627void GeneralFit::dp_vers_dtr(Vector const& dp,Vector const& tr,Vector& dtr)
1628{
1629 for(int i=0;i<mNPar;i++) {
1630 if( fixParam[i] ) continue;
1631 if( ! boundParam[i] ) dtr(i) = dp(i);
1632 else dtr(i) = (1.+tr(i)*tr(i))/D(i) * dp(i);
1633 }
1634}
1635
1636//////////////////////////////////////////////////////////////////////
1637/*!
1638 \verbatim
1639 dp = D/(1+tr**2) * dtr = coeff * dtr
1640 attention: df/dtr = D/(1+tr**2) * dF/dp = coeff * dF/dp
1641 \endverbatim
1642*/
1643double GeneralFit::c_dtr_vers_dp(int i,double tr)
1644{
1645 // ASSERT(i>=0 && i<mNPar);
1646 double coeff = 1.;
1647 if(boundParam[i]) coeff = D(i)/(1.+tr*tr);
1648 return(coeff);
1649}
1650
1651//////////////////////////////////////////////////////////////////////
1652Vector GeneralFit::dtr_vers_dp(Vector const& dtr,Vector const& tr)
1653{
1654 Vector dp(dtr);
1655 for(int i=0;i<mNPar;i++) {
1656 if( fixParam[i] || ! boundParam[i] ) continue;
1657 dp(i) *= c_dtr_vers_dp(i,tr(i));
1658 }
1659 return(dp);
1660}
1661
1662//////////////////////////////////////////////////////////////////////
1663// inline fonction pour aller + vite dans le try()
1664//void GeneralFit::dtr_vers_dp(Vector const& dtr,Vector const& tr,Vector& dp)
1665
1666//////////////////////////////////////////////////////////////////////
1667/*!
1668 \verbatim
1669 1-/ Redefinit dp pour qu'il soit superieur a minStepDeriv
1670 2-/ Redefinit dp pour que p+/-dp reste dans les limites (parametre borne)
1671 Si hors limites alors:
1672 p-dp <= min_p : dp = (p-min_p)*dist
1673 p+dp >= max_p : dp = (max_p-p)*dist
1674 \endverbatim
1675*/
1676int GeneralFit::put_in_limits_for_deriv(Vector const& p,Vector& dp,double dist)
1677{
1678 int nchanged = 0;
1679 bool changed;
1680 double dp_old;
1681
1682 for(int i=0;i<mNPar;i++) {
1683 if( fixParam[i] ) {dp(i)=0.; continue;} // Pas calcul derivee pour param fixe
1684
1685 if( fabs(dp(i))<minStepDeriv(i) ) {
1686 // On ne redefinit dp que si minStepDeriv>0.
1687 dp_old = dp(i);
1688 if(dp(i)>=0.) dp(i) = minStepDeriv(i); else dp(i) = -minStepDeriv(i);
1689 if(debugLevel>=2)
1690 cout<<"put_in_limits_for_deriv(range) dp["<<i<<"]=abs("<<dp_old
1691 <<") <"<<minStepDeriv(i)<<" changed to "<<dp(i)<<endl;
1692 }
1693
1694 if( !boundParam[i] ) continue;
1695
1696 changed = false;
1697 if( p(i)-dp(i)<=minParam(i) ) {
1698 dp_old = dp(i);
1699 dp(i) = dist*(p(i)-minParam(i));
1700 changed = true;
1701 if(debugLevel>=2)
1702 cout<<"put_in_limits_for_deriv(min) p["<<i<<"}="<<p(i)<<" >="
1703 <<minParam(i)<<" .. dp="<<dp_old<<" -> dp="<<dp(i)<<endl;
1704 }
1705
1706 if( p(i)+dp(i)>=maxParam(i) ) {
1707 dp_old = dp(i);
1708 dp(i) = dist*(maxParam(i)-p(i));
1709 changed = true;
1710 if(debugLevel>=2)
1711 cout<<"put_in_limits_for_deriv(max) p["<<i<<"]="<<p(i)<<" <="
1712 <<maxParam(i)<<" .. dp="<<dp_old<<" -> dp="<<dp(i)<<endl;
1713 }
1714
1715 if(changed) nchanged++;
1716 }
1717
1718 return nchanged;
1719}
1720
Note: See TracBrowser for help on using the repository browser.