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

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

Creation module DPC/NTools Reza 09/04/99

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