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

Last change on this file since 3468 was 3205, checked in by ansari, 18 years ago

Suppression flags MWERKS (compilo CodeWarrior pour MacOS8,9) , Reza 10/04/2007

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