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

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

Rationalisation mac. D. Y.

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