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

Last change on this file since 682 was 682, checked in by ansari, 26 years ago

Compilation Mac pour CodeWarrior PRO 5

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