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

Last change on this file since 4052 was 3587, checked in by ansari, 17 years ago

Adaptation suite nettoyage/suppression TRY/CATCH... , Reza 05/03/2009

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