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

Last change on this file since 3083 was 3083, checked in by cmv, 19 years ago

extraction de GeneralFunction+ GeneralFunc de generalfit.h,cc -> generalfunc.h,cc cmv 19/09/2006

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