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

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

elimination des OVector/OMatrix au profit des TVector/TMatrix cmv 25/10/99

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