Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TFumili.cxx
Go to the documentation of this file.
1// @(#)root/fumili:$Id$
2// Author: Stanislav Nesterov 07/05/2003
3
4
5/** \class TFumili
6
7### FUMILI minimization package
8
9FUMILI is based on ideas, proposed by I.N. Silin [See NIM A440, 2000 (p431)].
10It was converted from FORTRAN to C by Sergey Yaschenko <s.yaschenko@fz-juelich.de>
11
12
13FUMILI is used to minimize Chi-square function or to search maximum of
14likelihood function.
15
16Experimentally measured values \f$F_i\f$ are fitted with theoretical
17functions \f$f_i({\vec x}_i,\vec\theta\,\,)\f$, where \f${\vec x}_i\f$ are
18coordinates, and \f$\vec\theta\f$ -- vector of parameters.
19
20For better convergence Chi-square function has to be the following form
21
22\f[
23{\chi^2\over2}={1\over2}\sum^n_{i=1}\left(f_i(\vec
24x_i,\vec\theta\,\,)-F_i\over\sigma_i\right)^2 \tag{1}
25\f]
26
27where \f$\sigma_i\f$ are errors of measured function.
28
29The minimum condition is
30
31\f[
32{\partial\chi^2\over\partial\theta_i}=\sum^n_{j=1}{1\over\sigma^2_j}\cdot
33{\partial f_j\over\partial\theta_i}\left[f_j(\vec
34x_j,\vec\theta\,\,)-F_j\right]=0,\qquad i=1\ldots m\tag{2}
35\f]
36
37where m is the quantity of parameters.
38
39Expanding left part of (2) over parameter increments and
40retaining only linear terms one gets
41
42\f[
43\left(\partial\chi^2\over\theta_i\right)_{\vec\theta={\vec\theta}^0}
44+\sum_k\left(\partial^2\chi^2\over\partial\theta_i\partial\theta_k\right)_{
45\vec\theta={\vec\theta}^0}\cdot(\theta_k-\theta_k^0)
46= 0\tag{3}
47\f]
48
49Here \f${\vec\theta}_0\f$ is some initial value of parameters. In general case:
50
51\f[
52{\partial^2\chi^2\over\partial\theta_i\partial\theta_k}=
53\sum^n_{j=1}{1\over\sigma^2_j}{\partial f_j\over\theta_i}
54{\partial f_j\over\theta_k} +
55\sum^n_{j=1}{(f_j - F_j)\over\sigma^2_j}\cdot
56{\partial^2f_j\over\partial\theta_i\partial\theta_k}\tag{4}
57\f]
58
59In FUMILI algorithm for second derivatives of Chi-square approximate
60expression is used when last term in (4) is discarded. It is often
61done, not always wittingly, and sometimes causes troubles, for example,
62if user wants to limit parameters with positive values by writing down
63\f$\theta_i^2\f$ instead of \f$\theta_i\f$. FUMILI will fail if one tries
64minimize \f$\chi^2 = g^2(\vec\theta)\f$ where g is arbitrary function.
65
66Approximate value is:
67\f[{\partial^2\chi^2\over\partial\theta_i\partial\theta_k}\approx
68Z_{ik}=
69\sum^n_{j=1}{1\over\sigma^2_j}{\partial f_j\over\theta_i}
70{\partial f_j\over\theta_k}\tag{5}
71\f]
72
73Then the equations for parameter increments are
74\f[\left(\partial\chi^2\over\partial\theta_i\right)_{\vec\theta={\vec\theta}^0}
75+\sum_k Z_{ik}\cdot(\theta_k-\theta^0_k) = 0,
76\qquad i=1\ldots m\tag{6}
77\f]
78
79Remarkable feature of algorithm is the technique for step
80restriction. For an initial value of parameter \f${\vec\theta}^0\f$ a
81parallelepiped \f$P_0\f$ is built with the center at \f${\vec\theta}^0\f$ and
82axes parallel to coordinate axes \f$\theta_i\f$. The lengths of
83parallelepiped sides along i-th axis is \f$2b_i\f$, where \f$b_i\f$ is such a
84value that the functions \f$f_j(\vec\theta)\f$ are quasi-linear all over
85the parallelepiped.
86
87FUMILI takes into account simple linear inequalities in the form:
88\f[
89\theta_i^{\rm min}\le\theta_i\le\theta^{\rm max}_i\tag{7}
90\f]
91
92They form parallelepiped \f$P\f$ (\f$P_0\f$ may be deformed by \f$P\f$).
93Very similar step formulae are used in FUMILI for negative logarithm
94of the likelihood function with the same idea - linearization of
95function argument.
96
97*/
98
99
100#include "TFumili.h"
101
102#include <iostream>
103#include "TGraphAsymmErrors.h"
104#include "TF1.h"
105#include "TF2.h"
106#include "TF3.h"
107#include "TH1.h"
108#include "TMath.h"
109#include "TROOT.h"
110#include "TList.h"
111#include "TVirtualFitter.h"
112
113#include <iostream>
114
115
119
120
121
123// Machine dependent values fiXME!!
124// But don't set min=max=0 if param is unlimited
126static const Double_t gMINDOUBLE=-1e300;
127
128////////////////////////////////////////////////////////////////////////////////
129
131{//----------- FUMILI constructor ---------
132 // maxpar is the maximum number of parameters used with TFumili object
133 //
135 BuildArrays();
136
137 fNumericDerivatives = true;
138 fLogLike = false;
140 fGRAD = false;
141 fWARN = true;
142 fDEBUG = false;
143 fNlog = 0;
144 fSumLog = nullptr;
145 fNED1 = 0;
146 fNED2 = 0;
148 fEXDA = nullptr;
149 fFCN = nullptr;
150 fNfcn = 0;
151 fRP = 1.e-15; //precision
152 fS = 1e10;
153 fEPS =0.01;
154 fENDFLG = 0;
155 fNlimMul = 2;
156 fNmaxIter= 150;
157 fNstepDec= 3;
158 fLastFixed = -1;
159
160 fAKAPPA = 0.;
161 fGT = 0.;
162 for (int i = 0; i<5; ++i) fINDFLG[i] = 0;
163
164 SetName("Fumili");
165 gFumili = this;
166 gROOT->GetListOfSpecials()->Add(gFumili);
167}
168
170 fNpar = ParNum;
171 if (fNpar > fMaxParam) {
172 DeleteArrays();
174 BuildArrays();
175 }
176};
177
178////////////////////////////////////////////////////////////////////////////////
179///
180/// Allocates memory for internal arrays. Called by TFumili::TFumili
181///
182
185 fA = new Double_t[fMaxParam];
186 fPL0 = new Double_t[fMaxParam];
187 fPL = new Double_t[fMaxParam];
189 fDA = new Double_t[fMaxParam];
190 fAMX = new Double_t[fMaxParam];
191 fAMN = new Double_t[fMaxParam];
192 fR = new Double_t[fMaxParam];
193 fDF = new Double_t[fMaxParam];
194 fGr = new Double_t[fMaxParam];
196
197 // fX = new Double_t[10];
198
200 fZ0 = new Double_t[zSize];
201 fZ = new Double_t[zSize];
202
203 for (Int_t i=0;i<fMaxParam;i++) {
204 fA[i] =0.;
205 fDF[i]=0.;
206 fAMN[i]=gMINDOUBLE;
207 fAMX[i]=gMAXDOUBLE;
208 fPL0[i]=.1;
209 fPL[i] =.1;
210 fParamError[i]=0.;
211 fANames[i]=Form("%d",i);
212 }
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// TFumili destructor
217
219 DeleteArrays();
220 if (gROOT && !gROOT->TestBit(TObject::kInvalidObject))
221 gROOT->GetListOfSpecials()->Remove(this);
222 if (gFumili == this) gFumili = nullptr;
223}
224
225////////////////////////////////////////////////////////////////////////////////
226/// return a chisquare equivalent
227
229{
230 Double_t amin = 0;
231 H1FitChisquareFumili(npar,params,amin,params,1);
232 return 2*amin;
233}
234
235////////////////////////////////////////////////////////////////////////////////
236///
237/// Resets all parameter names, values and errors to zero
238///
239/// Argument opt is ignored
240///
241/// NB: this procedure doesn't reset parameter limits
242
244{
246 fNfcn = 0;
247 for (Int_t i=0;i<fNpar;i++) {
248 fA[i] =0.;
249 fDF[i] =0.;
250 fPL0[i] =.1;
251 fPL[i] =.1;
252 fAMN[i] = gMINDOUBLE;
253 fAMX[i] = gMAXDOUBLE;
254 fParamError[i]=0.;
255 fANames[i]=Form("%d",i);
256 }
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Deallocates memory. Called from destructor TFumili::~TFumili
261
263 delete[] fCmPar;
264 delete[] fANames;
265 delete[] fDF;
266 // delete[] fX;
267 delete[] fZ0;
268 delete[] fZ;
269 delete[] fGr;
270 delete[] fA;
271 delete[] fPL0;
272 delete[] fPL;
273 delete[] fDA;
274 delete[] fAMN;
275 delete[] fAMX;
276 delete[] fParamError;
277 delete[] fR;
278}
279
280////////////////////////////////////////////////////////////////////////////////
281///
282/// Calculates partial derivatives of theoretical function
283///
284/// Input:
285/// - fX - vector of data point
286///
287/// Output:
288/// - DF - array of derivatives
289///
290/// ARITHM.F: Converted from CERNLIB
291
293 Double_t ff,ai,hi,y,pi;
294 y = EvalTFN(df,fX);
295 for (Int_t i=0;i<fNpar;i++) {
296 df[i]=0;
297 if(fPL0[i]>0.) {
298 ai = fA[i]; // save current parameter value
299 hi = 0.01*fPL0[i]; // diff step
300 pi = fRP*TMath::Abs(ai);
301 if (hi<pi) hi = pi; // if diff step is less than precision
302 fA[i] = ai+hi;
303
304 if (fA[i]>fAMX[i]) { // if param is out of limits
305 fA[i] = ai-hi;
306 hi = -hi;
307 if (fA[i]<fAMN[i]) { // again out of bounds
308 fA[i] = fAMX[i]; // set param to high limit
309 hi = fAMX[i]-ai;
310 if (fAMN[i]-ai+hi<0) { // if hi < (ai-fAMN)
311 fA[i]=fAMN[i];
312 hi=fAMN[i]-ai;
313 }
314 }
315 }
316 ff = EvalTFN(df,fX);
317 df[i] = (ff-y)/hi;
318 fA[i] = ai;
319 }
320 }
321}
322
323
324////////////////////////////////////////////////////////////////////////////////
325/// Evaluate the minimisation function
326///
327/// Input parameters:
328/// - npar: number of currently variable parameters
329/// - par: array of (constant and variable) parameters
330/// - flag: Indicates what is to be calculated
331/// - grad: array of gradients
332///
333/// Output parameters:
334/// - fval: The calculated function value.
335/// - grad: The vector of first derivatives.
336///
337/// The meaning of the parameters par is of course defined by the user,
338/// who uses the values of those parameters to calculate their function value.
339/// The starting values must be specified by the user.
340///
341/// Inside FCN user has to define Z-matrix by means TFumili::GetZ
342/// and TFumili::Derivatives,
343/// set theoretical function by means of TFumili::SetUserFunc,
344/// but first - pass number of parameters by TFumili::SetParNumber
345///
346/// Later values are determined by Fumili as it searches for the minimum
347/// or performs whatever analysis is requested by the user.
348///
349/// The default function calls the function specified in SetFCN
350
352{
353 if (fFCN) (*fFCN)(npar,grad,fval,par,flag);
354 return npar;
355}
356
357
358////////////////////////////////////////////////////////////////////////////////
359/// Evaluate theoretical function
360/// - df: array of partial derivatives
361/// - X: vector of theoretical function argument
362
364{
365 // for the time being disable possibility to compute derivatives
366 //if(fTFN)
367 // return (*fTFN)(df,X,fA);
368 //else if(fTFNF1) {
369
370 TF1 *f1 = (TF1*)fUserFunc;
371 return f1->EvalPar(X,fA);
372 //}
373 //return 0.;
374}
375
376////////////////////////////////////////////////////////////////////////////////
377///
378/// Execute MINUIT commands. MINImize, SIMplex, MIGrad and FUMili all
379/// will call TFumili::Minimize method.
380///
381/// For full command list see
382/// MINUIT. Reference Manual. CERN Program Library Long Writeup D506.
383///
384/// Improvement and errors calculation are not yet implemented as well
385/// as Monte-Carlo seeking and minimization.
386/// Contour commands are also unsupported.
387///
388/// - command : command string
389/// - args : array of arguments
390/// - nargs : number of arguments
391
394 static TString clower = "abcdefghijklmnopqrstuvwxyz";
395 static TString cupper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
396 const Int_t nntot = 40;
397 const char *cname[nntot] = {
398 "MINImize ", // 0 checked
399 "SEEk ", // 1 none
400 "SIMplex ", // 2 checked same as 0
401 "MIGrad ", // 3 checked same as 0
402 "MINOs ", // 4 none
403 "SET xxx ", // 5 lot of stuff
404 "SHOw xxx ", // 6 -----------
405 "TOP of pag", // 7 .
406 "fiX ", // 8 .
407 "REStore ", // 9 .
408 "RELease ", // 10 .
409 "SCAn ", // 11 not yet implemented
410 "CONtour ", // 12 not yet implemented
411 "HESse ", // 13 not yet implemented
412 "SAVe ", // 14 obsolete
413 "IMProve ", // 15 not yet implemented
414 "CALl fcn ", // 16 .
415 "STAndard ", // 17 .
416 "END ", // 18 .
417 "EXIt ", // 19 .
418 "RETurn ", // 20 .
419 "CLEar ", // 21 .
420 "HELP ", // 22 not yet implemented
421 "MNContour ", // 23 not yet implemented
422 "STOp ", // 24 .
423 "JUMp ", // 25 not yet implemented
424 " ", //
425 " ", //
426 "FUMili ", // 28 checked same as 0
427 " ", //
428 " ", //
429 " ", //
430 " ", //
431 "COVARIANCE", // 33
432 "PRINTOUT ", // 34
433 "GRADIENT ", // 35
434 "MATOUT ", // 36
435 "ERROR DEF ", // 37
436 "LIMITS ", // 38
437 "PUNCH "}; // 39
438
439
440 fCword = comand;
441 fCword.ToUpper();
442 if (nargs<=0) fCmPar[0] = 0;
443 Int_t i;
444 for(i=0;i<fMaxParam;i++) {
445 if(i<nargs) fCmPar[i] = args[i];
446 }
447 /*
448 fNmaxIter = int(fCmPar[0]);
449 if (fNmaxIter <= 0) {
450 fNmaxIter = fNpar*10 + 20 + fNpar*M*5;
451 }
452 fEPS = fCmPar[1];
453 */
454 //*-*- look for command in list CNAME . . . . . . . . . .
455 TString ctemp = fCword(0,3);
456 Int_t ind;
457 for (ind = 0; ind < nntot; ++ind) {
458 if (strncmp(ctemp.Data(),cname[ind],3) == 0) break;
459 }
460 if (ind==nntot) return -3; // Unknown command - input ignored
461 if (fCword(0,4) == "MINO") ind=3;
462 switch (ind) {
463 case 0: case 3: case 2: case 28:
464 // MINImize [maxcalls] [tolerance]
465 // also SIMplex, MIGrad and FUMili
466 if(nargs>=1)
467 fNmaxIter=TMath::Max(Int_t(fCmPar[0]),fNmaxIter); // fiXME!!
468 if(nargs==2)
469 fEPS=fCmPar[1];
470 return Minimize();
471 case 1:
472 // SEEk not implemented in this package
473 return -10;
474
475 case 4: // MINos errors analysis not implemented
476 return -10;
477
478 case 5: case 6: // SET xxx & SHOW xxx
479 return ExecuteSetCommand(nargs);
480
481 case 7: // Obsolete command
482 Printf("1");
483 return 0;
484 case 8: // fiX <parno> ....
485 if (nargs<1) return -1; // No parameters specified
486 for (i=0;i<nargs;i++) {
487 Int_t parnum = Int_t(fCmPar[i])-1;
489 }
490 return 0;
491 case 9: // REStore <code>
492 if (nargs<1) return 0;
493 if(fCmPar[0]==0.)
494 for (i=0;i<fNpar;i++)
496 else
497 if(fCmPar[0]==1.) {
499 std::cout <<fLastFixed<<std::endl;
500 }
501 return 0;
502 case 10: // RELease <parno> ...
503 if (nargs<1) return -1; // No parameters specified
504 for (i=0;i<nargs;i++) {
505 Int_t parnum = Int_t(fCmPar[i])-1;
507 }
508 return 0;
509 case 11: // SCAn not implemented
510 return -10;
511 case 12: // CONt not implemented
512 return -10;
513
514 case 13: // HESSe not implemented
515 return -10;
516 case 14: // SAVe
517 Printf("SAVe command is obsolete");
518 return -10;
519 case 15: // IMProve not implemented
520 return -10;
521 case 16: // CALl fcn <iflag>
522 {if(nargs<1) return -1;
523 Int_t flag = Int_t(fCmPar[0]);
526 return 0;}
527 case 17: // STAndard must call function STAND
528 return 0;
529 case 18: case 19:
530 case 20: case 24: {
532 Int_t flag = 3;
534 return 0;
535 }
536 case 21:
537 Clear();
538 return 0;
539 case 22: //HELp not implemented
540 case 23: //MNContour not implemented
541 case 25: // JUMp not implemented
542 return -10;
543 case 26: case 27: case 29: case 30: case 31: case 32:
544 return 0; // blank commands
545 case 33: case 34: case 35: case 36: case 37: case 38:
546 case 39:
547 Printf("Obsolete command. Use corresponding SET command instead");
548 return -10;
549 default:
550 break;
551 }
552 return 0;
553}
554
555////////////////////////////////////////////////////////////////////////////////
556/// Called from TFumili::ExecuteCommand in case
557/// of "SET xxx" and "SHOW xxx".
558
560 static Int_t nntot = 30;
561 static const char *cname[30] = {
562 "FCN value ", // 0 .
563 "PARameters", // 1 .
564 "LIMits ", // 2 .
565 "COVariance", // 3 .
566 "CORrelatio", // 4 .
567 "PRInt levl", // 5 not implemented yet
568 "NOGradient", // 6 .
569 "GRAdient ", // 7 .
570 "ERRor def ", // 8 not sure how to implement - by time being ignored
571 "INPut file", // 9 not implemented
572 "WIDth page", // 10 not implemented yet
573 "LINes page", // 11 not implemented yet
574 "NOWarnings", // 12 .
575 "WARnings ", // 13 .
576 "RANdom gen", // 14 not implemented
577 "TITle ", // 15 ignored
578 "STRategy ", // 16 ignored
579 "EIGenvalue", // 17 not implemented yet
580 "PAGe throw", // 18 ignored
581 "MINos errs", // 19 not implemented yet
582 "EPSmachine", // 20 .
583 "OUTputfile", // 21 not implemented
584 "BATch ", // 22 ignored
585 "INTeractiv", // 23 ignored
586 "VERsion ", // 24 .
587 "reserve ", // 25 .
588 "NODebug ", // 26 .
589 "DEBug ", // 27 .
590 "SHOw ", // 28 err
591 "SET "};// 29 err
592
594 Int_t i, ind;
596 for (ind = 0; ind < nntot; ++ind) {
597 ctemp = cname[ind];
598 ckind = ctemp(0,3);
599 ctemp2 = fCword(4,6);
600 if (strstr(ctemp2.Data(),ckind.Data())) break;
601 }
602 ctemp2 = fCword(0,3);
603 if(ctemp2.Contains("SET")) setCommand=true;
604 if(ctemp2.Contains("HEL") || ctemp2.Contains("SHO")) setCommand=false;
605
606 if (ind>=nntot) return -3;
607
608 switch(ind) {
609 case 0: // SET FCN value illegal // SHOw only
610 if(!setCommand) Printf("FCN=%f",fS);
611 return 0;
612 case 1: // PARameter <parno> <value>
613 {
614 if (nargs<2 && setCommand) return -1;
616 Double_t val;
617 if(setCommand) {
618 parnum = Int_t(fCmPar[0])-1;
619 val= fCmPar[1];
620 if(parnum<0 || parnum>=fNpar) return -2; //no such parameter
621 fA[parnum] = val;
622 } else {
623 if (nargs>0) {
624 parnum = Int_t(fCmPar[0])-1;
625 if(parnum<0 || parnum>=fNpar) return -2; //no such parameter
626 Printf("Parameter %s = %E",fANames[parnum].Data(),fA[parnum]);
627 } else
628 for (i=0;i<fNpar;i++)
629 Printf("Parameter %s = %E",fANames[i].Data(),fA[i]);
630
631 }
632 return 0;
633 }
634 case 2: // LIMits [parno] [ <lolim> <uplim> ]
635 {
638 if (nargs<1) {
639 for(i=0;i<fNpar;i++)
640 if(setCommand) {
641 fAMN[i] = gMINDOUBLE;
642 fAMX[i] = gMAXDOUBLE;
643 } else
644 Printf("Limits for param %s: Low=%E, High=%E",
645 fANames[i].Data(),fAMN[i],fAMX[i]);
646 } else {
647 parnum = Int_t(fCmPar[0])-1;
648 if(parnum<0 || parnum>=fNpar)return -1;
649 if(setCommand) {
650 if(nargs>2) {
651 lolim = fCmPar[1];
652 uplim = fCmPar[2];
653 if(uplim==lolim) return -1;
654 if(lolim>uplim) {
655 Double_t tmp = lolim;
656 lolim = uplim;
657 uplim = tmp;
658 }
659 } else {
662 }
663 fAMN[parnum] = lolim;
664 fAMX[parnum] = uplim;
665 } else
666 Printf("Limits for param %s Low=%E, High=%E",
667 fANames[parnum].Data(),fAMN[parnum],fAMX[parnum]);
668 }
669 return 0;
670 }
671 case 3:
672 {
673 if(setCommand) return 0;
674 Printf("\nCovariant matrix ");
675 Int_t l = 0,nn=0,nnn=0;
676 for (i=0;i<fNpar;i++) if(fPL0[i]>0.) nn++;
677 for (i=0;i<nn;i++) {
678 for(;fPL0[nnn]<=0.;nnn++) { }
679 printf("%5s: ",fANames[nnn++].Data());
680 for (Int_t j=0;j<=i;j++)
681 printf("%11.2E",fZ[l++]);
682 std::cout<<std::endl;
683 }
684 std::cout<<std::endl;
685 return 0;
686 }
687 case 4:
688 if(setCommand) return 0;
689 Printf("\nGlobal correlation factors (maximum correlation of the parameter\n with arbitrary linear combination of other parameters)");
690 for(i=0;i<fNpar;i++) {
691 printf("%5s: ",fANames[i].Data());
692 printf("%11.3E\n",TMath::Sqrt(1-1/((fR[i]!=0.)?fR[i]:1.)) );
693 }
694 std::cout<<std::endl;
695 return 0;
696 case 5: // PRIntout not implemented
697 return -10;
698 case 6: // NOGradient
699 if(!setCommand) return 0;
700 fGRAD = false;
701 return 0;
702 case 7: // GRAdient
703 if(!setCommand) return 0;
704 fGRAD = true;
705 return 0;
706 case 8: // ERRordef - now ignored
707 return 0;
708 case 9: // INPut - not implemented
709 return -10;
710 case 10: // WIDthpage - not implemented
711 return -10;
712 case 11: // LINesperpage - not implemented
713 return -10;
714 case 12: //NOWarnings
715 if(!setCommand) return 0;
716 fWARN = false;
717 return 0;
718 case 13: // WARnings
719 if(!setCommand) return 0;
720 fWARN = true;
721 return 0;
722 case 14: // RANdomgenerator - not implemented
723 return -10;
724 case 15: // TITle - ignored
725 return 0;
726 case 16: // STRategy - ignored
727 return 0;
728 case 17: // EIGenvalues - not implemented
729 return -10;
730 case 18: // PAGethrow - ignored
731 return 0;
732 case 19: // MINos errors - not implemented
733 return -10;
734 case 20: //EPSmachine
735 if(!setCommand) {
736 Printf("Relative floating point precision RP=%E",fRP);
737 } else
738 if (nargs>0) {
741 }
742 return 0;
743 case 21: // OUTputfile - not implemented
744 return -10;
745 case 22: // BATch - ignored
746 return 0;
747 case 23: // INTerative - ignored
748 return 0;
749 case 24: // VERsion
750 if(setCommand) return 0;
751 Printf("FUMILI-ROOT version 0.1");
752 return 0;
753 case 25: // reserved
754 return 0;
755 case 26: // NODebug
756 if(!setCommand) return 0;
757 fDEBUG = false;
758 return 0;
759 case 27: // DEBug
760 if(!setCommand) return 0;
761 fDEBUG = true;
762 return 0;
763 case 28:
764 case 29:
765 return -3;
766 default:
767 break;
768 }
769 return -3;
770}
771
772////////////////////////////////////////////////////////////////////////////////
773/// Fixes parameter number ipar
774
776 if(ipar>=0 && ipar<fNpar && fPL0[ipar]>0.) {
777 fPL0[ipar] = -fPL0[ipar];
778 fLastFixed = ipar;
779 }
780}
781
782////////////////////////////////////////////////////////////////////////////////
783/// Return a pointer to the covariance matrix
784
786{
787 return fZ;
788
789}
790
791////////////////////////////////////////////////////////////////////////////////
792/// Return element i,j from the covariance matrix
793
795{
796 if (!fZ) return 0;
798 Error("GetCovarianceMatrixElement","Illegal arguments i=%d, j=%d",i,j);
799 return 0;
800 }
801 return fZ[j+fNpar*i];
802}
803
804////////////////////////////////////////////////////////////////////////////////
805/// Return the total number of parameters (free + fixed)
806
808{
809 return fNpar;
810}
811
812////////////////////////////////////////////////////////////////////////////////
813/// Return the number of free parameters
814
816{
817 Int_t nfree = fNpar;
818 for (Int_t i=0;i<fNpar;i++) {
819 if (IsFixed(i)) nfree--;
820 }
821 return nfree;
822}
823
824////////////////////////////////////////////////////////////////////////////////
825/// Return error of parameter ipar
826
828{
829 if (ipar<0 || ipar>=fNpar) return 0;
830 else return fParamError[ipar];
831}
832
833////////////////////////////////////////////////////////////////////////////////
834/// Return current value of parameter ipar
835
837{
838 if (ipar<0 || ipar>=fNpar) return 0;
839 else return fA[ipar];
840}
841
842////////////////////////////////////////////////////////////////////////////////
843/// Get various ipar parameter attributes:
844///
845/// - cname: parameter name
846/// - value: parameter value
847/// - verr: parameter error
848/// - vlow: lower limit
849/// - vhigh: upper limit
850///
851/// WARNING! parname must be suitably dimensioned in the calling function.
852
854{
856 value = 0;
857 verr = 0;
858 vlow = 0;
859 vhigh = 0;
860 return -1;
861 }
862 strcpy(cname,fANames[ipar].Data());
863 value = fA[ipar];
864 verr = fParamError[ipar];
865 vlow = fAMN[ipar];
866 vhigh = fAMX[ipar];
867 return 0;
868}
869
870////////////////////////////////////////////////////////////////////////////////
871/// Return name of parameter ipar
872
873const char *TFumili::GetParName(Int_t ipar) const
874{
875 if (ipar < 0 || ipar > fNpar) return "";
876 return fANames[ipar].Data();
877}
878
879////////////////////////////////////////////////////////////////////////////////
880/// Return errors after MINOs
881/// not implemented
882
884{
885 eparab = 0;
886 globcc = 0;
888 eplus = 0;
889 eminus = 0;
890 return -1;
891 }
892 eplus=fParamError[ipar];
893 eminus=-eplus;
894 return 0;
895}
896
897////////////////////////////////////////////////////////////////////////////////
898/// Return global fit parameters
899/// - amin : chisquare
900/// - edm : estimated distance to minimum
901/// - errdef
902/// - nvpar : number of variable parameters
903/// - nparx : total number of parameters
904
906{
907 amin = 2*fS;
908 edm = fGT; //
909 errdef = 0; // ??
910 nparx = fNpar;
911 nvpar = 0;
912 for(Int_t ii=0; ii<fNpar; ii++) {
913 if(fPL0[ii]>0.) nvpar++;
914 }
915 return 0;
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// Return Sum(log(i) i=0,n
920/// used by log-likelihood fits
921
923{
924 if (n < 0) return 0;
925 if (n > fNlog) {
926 if (fSumLog) delete [] fSumLog;
927 fNlog = 2*n+1000;
928 fSumLog = new Double_t[fNlog+1];
929 Double_t fobs = 0;
930 for (Int_t j=0;j<=fNlog;j++) {
931 if (j > 1) fobs += TMath::Log(j);
932 fSumLog[j] = fobs;
933 }
934 }
935 if (fSumLog) return fSumLog[n];
936 return 0;
937}
938
939////////////////////////////////////////////////////////////////////////////////
940/// Inverts packed diagonal matrix Z by square-root method.
941/// Matrix elements corresponding to
942/// fix parameters are removed.
943///
944/// - n: number of variable parameters
945
947{
948 static Double_t am = 3.4e138;
949 static Double_t rp = 5.0e-14;
950 Double_t ap, aps, c, d;
951 Double_t *r_1=fR;
953 Double_t *z_1=fZ;
954 Int_t i, k, l, ii, ki, li, kk, ni, ll, nk, nl, ir, lk;
955 if (n < 1) {
956 return;
957 }
958 --pl_1;
959 --r_1;
960 --z_1;
961 aps = am / n;
962 aps = sqrt(aps);
963 ap = 1.0e0 / (aps * aps);
964 ir = 0;
965 for (i = 1; i <= n; ++i) {
966 L1:
967 ++ir;
968 if (pl_1[ir] <= 0.0e0) goto L1;
969 else goto L2;
970 L2:
971 ni = i * (i - 1) / 2;
972 ii = ni + i;
973 k = n + 1;
974 if (z_1[ii] <= rp * TMath::Abs(r_1[ir]) || z_1[ii] <= ap) {
975 goto L19;
976 }
977 z_1[ii] = 1.0e0 / sqrt(z_1[ii]);
978 nl = ii - 1;
979 L3:
980 if (nl - ni <= 0) goto L5;
981 else goto L4;
982 L4:
983 z_1[nl] *= z_1[ii];
984 if (TMath::Abs(z_1[nl]) >= aps) {
985 goto L16;
986 }
987 --nl;
988 goto L3;
989 L5:
990 if (i - n >= 0) goto L12;
991 else goto L6;
992 L6:
993 --k;
994 nk = k * (k - 1) / 2;
995 nl = nk;
996 kk = nk + i;
997 d = z_1[kk] * z_1[ii];
998 c = d * z_1[ii];
999 l = k;
1000 L7:
1001 ll = nk + l;
1002 li = nl + i;
1003 z_1[ll] -= z_1[li] * c;
1004 --l;
1005 nl -= l;
1006 if (l - i <= 0) goto L9;
1007 else goto L7;
1008 L8:
1009 ll = nk + l;
1010 li = ni + l;
1011 z_1[ll] -= z_1[li] * d;
1012 L9:
1013 --l;
1014 if (l <= 0) goto L10;
1015 else goto L8;
1016 L10:
1017 z_1[kk] = -c;
1018 if (k - i - 1 <= 0) goto L11;
1019 else goto L6;
1020 L11:
1021 ;
1022 }
1023 L12:
1024 for (i = 1; i <= n; ++i) {
1025 for (k = i; k <= n; ++k) {
1026 nl = k * (k - 1) / 2;
1027 ki = nl + i;
1028 d = 0.0e0;
1029 for (l = k; l <= n; ++l) {
1030 li = nl + i;
1031 lk = nl + k;
1032 d += z_1[li] * z_1[lk];
1033 nl += l;
1034 }
1035 ki = k * (k - 1) / 2 + i;
1036 z_1[ki] = d;
1037 }
1038 }
1039 L15:
1040 return;
1041 L16:
1042 k = i + nl - ii;
1043 ir = 0;
1044 for (i = 1; i <= k; ++i) {
1045 L17:
1046 ++ir;
1047 if (pl_1[ir] <= 0.0e0) {
1048 goto L17;
1049 }
1050 }
1051 L19:
1052 pl_1[ir] = -2.0e0;
1053 r_1[ir] = 0.0e0;
1054 fINDFLG[0] = ir - 1;
1055 goto L15;
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Return kTRUE if parameter ipar is fixed, kFALSE otherwise)
1060
1062{
1064 Warning("IsFixed","Illegal parameter number :%d",ipar);
1065 return kFALSE;
1066 }
1067 if (fPL0[ipar] < 0) return kTRUE;
1068 else return kFALSE;
1069}
1070
1071void PrintVector(const char * name, int n, double * x) {
1072 // print vector data
1073 std::cout << name << " : {";
1074 for (int i = 0; i < n; i++)
1075 std::cout << " " << x[i];
1076 std::cout << " }\n";
1077}
1078void PrintMatrix(const char * name, int n, double * x) {
1079 // print matrix data
1080 std::cout << name << " : \n";
1081 int index = 0;
1082 for (int i = 0; i < n; i++) {
1083 for (int j = 0; j <= i; j++) {
1084 std::cout << " " << x[index];
1085 index++;
1086 }
1087 std::cout << std::endl;
1088 }
1089 std::cout << "\n";
1090}
1091
1092////////////////////////////////////////////////////////////////////////////////
1093/// Main minimization procedure
1094///
1095/// This function is called after setting theoretical function
1096/// by means of TFumili::SetUserFunc and initializing parameters.
1097/// Optionally one can set FCN function (see TFumili::SetFCN and TFumili::Eval)
1098/// If FCN is undefined then user has to provide data arrays by calling
1099/// TFumili::SetData procedure.
1100///
1101/// TFumili::Minimize return following values:
1102/// - 0 - fit is converged
1103/// - -2 - function is not decreasing (or bad derivatives)
1104/// - -3 - error estimations are infinite
1105/// - -4 - maximum number of iterations is exceeded
1106
1108{
1109 Int_t i;
1110 // Flag3 - is fit is chi2 or likelihood? 0 - chi2, 1 - likelihood
1111 fINDFLG[2]=0;
1112 //
1113 // Are the parameters outside of the boundaries ?
1114 //
1115 Int_t parn;
1116
1117 // I think this funciton call is needed for getting fA and fNpar
1118 // and fAMX fAMN ?
1119 if(fFCN) {
1120 Eval(parn,fGr,fS,fA,9); fNfcn++;
1121 }
1122 for( i = 0; i < fNpar; i++) {
1123 if(fA[i] > fAMX[i]) fA[i] = fAMX[i];
1124 if(fA[i] < fAMN[i]) fA[i] = fAMN[i];
1125 }
1126
1127 Int_t nn2, n, fixFLG, ifix1, fi, nn3, nn1, n0;
1128 Double_t t1;
1129 Double_t sp, t = 0, olds=0;
1130 Double_t bi, aiMAX=0, amb;
1132 Double_t alambd, al, bm, abi, abm;
1133 Int_t l1, k, ifix;
1134
1135 nn2=0;
1136
1137 // Number of parameters;
1138 n=fNpar;
1139 fixFLG=0;
1140
1141 // Exit flag
1142 fENDFLG=0;
1143
1144 // Flag2
1145 fINDFLG[1] = 0;
1146 ifix1=-1;
1147 fi=0;
1148 nn3=0;
1149
1150 // Initialize param.step limits
1151 for( i=0; i < n; i++) {
1152 fR[i]=0.;
1153 if ( fEPS > 0.) fParamError[i] = 0.;
1154 fPL[i] = fPL0[i];
1155 }
1156
1157L3: // Start Iteration
1158
1159 nn1 = 1;
1160 t1 = 1.;
1161
1162
1163
1164//perform iteration
1165L4: // New iteration
1166
1167 if (fDEBUG) {
1168 std::cout << "New iteration - nfcn " << fNfcn << " nn1 = " << nn1 << " fGT " << fGT << "\n";
1169 PrintVector("Parameter",n,fA);
1170 PrintVector("PL ",n,fPL);
1171 PrintVector("Step ",n,fDA);
1172 }
1173
1174 // fS - objective function value - zero first
1175 fS = 0.;
1176 // n0 - number of variable parameters in fit
1177 n0 = 0;
1178 for( i = 0; i < n; i++) {
1179 fGr[i]=0.; // zero gradients
1180 if (fPL0[i] > .0) { // fLO is negative for fixed parameters
1181 n0=n0+1;
1182 // new iteration - new parallelepiped
1183 if (fPL[i] > .0) fPL0[i]=fPL[i];
1184 }
1185 }
1186 Int_t nn0;
1187 // Calculate number of fZ-matrix elements as nn0=1+2+..+n0
1188 nn0 = n0*(n0+1)/2;
1189 // if (nn0 >= 1) ????
1190 // fZ-matrix is initialized
1191 for( i=0; i < nn0; i++) fZ[i]=0.;
1192
1193 // Flag1
1194 fINDFLG[0] = 0;
1195 Int_t ijkl=1;
1196
1197 // Calculate fS - objective function, fGr - gradients, fZ - fZ-matrix
1198 if(fFCN) {
1199 Eval(parn,fGr,fS,fA,2);
1200 fNfcn++;
1201 } else
1202 ijkl = SGZ();
1203 if(!ijkl) return 10;
1204 if (ijkl == -1) fINDFLG[0]=1;
1205
1206 // sp - scaled on fS machine precision
1207 // compute precision epsilon (fRP is 1.E-15)
1209
1210 // save fZ-matrix
1211 for( i=0; i < nn0; i++) fZ0[i] = fZ[i];
1212 if (nn3 > 0) {
1213 if (nn1 <= fNstepDec) {
1214 // conditions on next step point
1215 t=2.*(fS-olds-fGT);
1216 if (fINDFLG[0] == 0) {
1217 if (TMath::Abs(fS-olds) <= sp && -fGT <= sp) goto L19;
1218 if (fDEBUG) std::cout << " factor t is " << -fGT/t << std::endl;
1219 if( 0.59*t < -fGT) goto L19;
1220 t = -fGT/t;
1221 if (t < 0.25 ) t = 0.25;
1222 }
1223 else t = 0.25;
1224 fGT = fGT*t;
1225 t1 = t1*t;
1226 nn2=0;
1227 // loop on parameter
1228 // change parameter value using step fPL and fDA
1229 for( i = 0; i < n; i++) {
1230 if (fPL[i] > 0.) {
1231 fA[i]=fA[i]-fDA[i];
1232 fPL[i]=fPL[i]*t;
1233 fDA[i]=fDA[i]*t;
1234 fA[i]=fA[i]+fDA[i];
1235 }
1236 }
1237 nn1=nn1+1;
1238 if (fDEBUG) {
1239 std::cout << "change all PL and steps by factor t " << t << std::endl;
1240 }
1241 goto L4;
1242 }
1243 }
1244
1245L19:
1246
1247 if (fDEBUG)
1248 std::cout << "exit iteration (L19) t = " << t << " fGT = " << fGT << std::endl;
1249
1250 // flag here should be equal to zero
1251 if(fINDFLG[0] != 0) {
1252 fENDFLG=-4;
1253 printf("trying to execute an illegal jump at L85\n");
1254 //goto L85;
1255 }
1256
1257
1258 Int_t k1, k2, i1, j, l;
1259 k1 = 1;
1260 k2 = 1;
1261 i1 = 1;
1262 // In this cycle we removed from fZ contributions from fixed parameters
1263 // We'll get fixed parameters after boundary check
1264 for( i = 0; i < n; i++) {
1265 if (fPL0[i] > .0) {
1266 // if parameter was fixed - release it
1267 if (fPL[i] == 0.) fPL[i]=fPL0[i];
1268 if (fPL[i] > .0) { // ??? it is already non-zero
1269 // if derivative is negative and we above maximum
1270 // or vice versa then fix parameter again and increment k1 by i1
1271 if ((fA[i] >= fAMX[i] && fGr[i] < 0.) ||
1272 (fA[i] <= fAMN[i] && fGr[i] > 0.)) {
1273 if (fDEBUG)
1274 std::cout << "Fix parameters with values outside boundary and negative derivative " << std::endl;
1275 fPL[i] = 0.;
1276 k1 = k1 + i1; // i1 stands for fZ-matrix row-number multiplier
1277 /// - skip this row
1278 // in case we are fixing parameter number i
1279 } else {
1280 for( j=0; j <= i; j++) {// cycle on columns of fZ-matrix
1281 if (fPL0[j] > .0) {
1282 // if parameter is not fixed then fZ = fZ0
1283 // Now matrix fZ of other dimension
1284 if (fPL[j] > .0) {
1285 fZ[k2 -1] = fZ0[k1 -1];
1286 k2=k2+1;
1287 }
1288 k1=k1+1;
1289 }
1290 }
1291 }
1292 }
1293 else k1 = k1 + i1; // In case of negative fPL[i] - after mconvd
1294 i1=i1+1; // Next row of fZ0
1295 }
1296 }
1297
1298 // INVERT fZ-matrix (mconvd() procedure)
1299 // fZ stores lower diagonal part of symmetrix matrix
1300 i1 = 1;
1301 l = 1;
1302 for( i = 0; i < n; i++) {// extract diagonal elements to fR-vector
1303 if (fPL[i] > .0) {
1304 fR[i] = fZ[l - 1];
1305 i1 = i1+1;
1306 l = l + i1;
1307 }
1308 }
1309
1310 n0 = i1 - 1;
1311 if (fDEBUG)
1312 PrintMatrix("Approximate Hessian matrix ",n0,fZ);
1313
1314 InvertZ(n0);
1315
1316 // fZ matrix now is inverted
1317 if (fINDFLG[0] != 0) { // problems
1318 if (fDEBUG)
1319 std::cout << "Some problems inverting the matrix - go back and try reducing again" << std::endl;
1320 // some PLs now have negative values, try to reduce fZ-matrix again
1321 fINDFLG[0] = 0;
1322 fINDFLG[1] = 1; // errors can be infinite
1323 fixFLG = fixFLG + 1;
1324 fi = 0;
1325 goto L19;
1326 }
1327
1328 if (fDEBUG) {
1329 PrintMatrix("Approximate Covariance matrix (inverse of Hessian ) ",n0,fZ);
1330 PrintVector("Current gradient",n,fGr);
1331 PrintVector("Current step",n,fDA);
1332 }
1333
1334 // ... CALCULATE THEORETICAL STEP TO MINIMUM
1335 i1 = 1;
1336 for( i = 0; i < n; i++) {
1337 fDA[i]=0.; // initial step is zero
1338 if (fPL[i] > .0) { // for non-fixed parameters
1339 l1=1;
1340 for( l = 0; l < n; l++) {
1341 if (fPL[l] > .0) {
1342 // Calculate offset of Z^-1(i1,l1) element in packed matrix
1343 // because we skip fixed param numbers we need also i,l
1344 if (i1 <= l1 ) k=l1*(l1-1)/2+i1;
1345 else k=i1*(i1-1)/2+l1;
1346 // dA_i = \sum (-Z^{-1}_{il}*grad(fS)_l)
1347 fDA[i]=fDA[i]-fGr[l]*fZ[k - 1];
1348 l1=l1+1;
1349 }
1350 }
1351 i1=i1+1;
1352 }
1353 }
1354 if (fDEBUG)
1355 PrintVector("theoretical step (Newton)",n,fDA);
1356
1357 // ... CHECK FOR PARAMETERS ON BOUNDARY
1358
1359 afix=0.;
1360 ifix = -1;
1361 i1 = 1;
1362 l = i1;
1363 for( i = 0; i < n; i++)
1364 if (fPL[i] > .0) {
1365 sigi = TMath::Sqrt(TMath::Abs(fZ[l - 1])); // calculate \sqrt{Z^{-1}_{ii}}
1366 // original fR is diagonal of Hessian (not inverted matrix)
1367 fR[i] = fR[i]*fZ[l - 1]; // Z_ii * Z^-1_ii
1368 if (fEPS > .0) fParamError[i]=sigi;
1369 if ((fA[i] >= fAMX[i] && fDA[i] > 0.) || (fA[i] <= fAMN[i]
1370 && fDA[i] < .0)) {
1371 // if parameter out of bounds and if step is making things worse
1372
1373 akap = TMath::Abs(fDA[i]/sigi);
1374 // let's found maximum of dA/sigi - the worst of parameter steps
1375 if (akap > afix) {
1376 afix=akap;
1377 ifix=i;
1378 ifix1=i;
1379 }
1380 if (fDEBUG)
1381 std::cout << "Parameter " << i << " is outside bounds "
1382 << akap << " " << afix << " " << ifix << std::endl;
1383 }
1384 i1=i1+1;
1385 l=l+i1;
1386 }
1387 if (ifix != -1) {
1388 // so the worst parameter is found - fix it and exclude,
1389 // reduce fZ-matrix again
1390 fPL[ifix] = -1.;
1391 fixFLG = fixFLG + 1;
1392 fi = 0;
1393
1394 if (fDEBUG) {
1395 std::cout << "Parameter " << ifix << " is the worst - fix it and repeat step calculation " << std::endl;
1396 }
1397 //.. REPEAT CALCULATION OF THEORETICAL STEP AFTER fiXING EACH PARAMETER
1398 goto L19;
1399 }
1400
1401 //... CALCULATE STEP CORRECTION FACTOR
1402
1403 alambd = 1.;
1404 fAKAPPA = 0.;
1405 Int_t imax;
1406 imax = -1;
1407
1408
1409 for( i = 0; i < n; i++) {
1410 if (fPL[i] > .0) {
1411 bm = fAMX[i] - fA[i];
1412 abi = fA[i] + fPL[i]; // upper parameter limit
1413 abm = fAMX[i];
1414 if (fDA[i] <= .0) {
1415 bm = fA[i] - fAMN[i];
1416 abi = fA[i] - fPL[i]; // lower parameter limit
1417 abm = fAMN[i];
1418 }
1419 bi = fPL[i];
1420 // if parallelepiped boundary is crossing limits
1421 // then reduce it (deforming)
1422 if ( bi > bm) {
1423 bi = bm;
1424 abi = abm;
1425 if (fDEBUG)
1426 std::cout << "Reduce parallelepide for "
1427 << i << " from " << fPL[i] << " to " << bi << std::endl;
1428 }
1429 // if calculated step is out of bounds
1430 if ( TMath::Abs(fDA[i]) > bi) {
1431 // decrease step splitter alambdA if needed
1432 // by definition al is less than 1
1433 al = TMath::Abs(bi/fDA[i]);
1434 if (fDEBUG)
1435 std::cout << "step out of bound for " << i << " reduce to " << al << std::endl;
1436 if (alambd > al) {
1437 imax=i;
1438 aiMAX=abi;
1439 alambd=al;
1440 }
1441 }
1442 // fAKAPPA - parameter will be <fEPS if fit is converged
1443 akap = TMath::Abs(fDA[i]/fParamError[i]);
1444 if (akap > fAKAPPA) fAKAPPA=akap;
1445 }
1446 }
1447
1448 if (fDEBUG)
1449 std::cout << "Compute now corrected step - min found correction factor " << alambd << " max of akappa " << fAKAPPA << " nn2 " << nn2 << std::endl;
1450 //... CALCULATE NEW CORRECTED STEP
1451 fGT = 0.;
1452 amb = 1.e18;
1453 // alambd - multiplier to split theoretical step dA
1454 if (alambd > .0) amb = 0.25/alambd;
1455 for( i = 0; i < n; i++) {
1456 if (fPL[i] > .0) {
1457 if (nn2 > fNlimMul ) {
1458 if (TMath::Abs(fDA[i]/fPL[i]) > amb ) {
1459 if (fDEBUG)
1460 std::cout << "increase parallelipid 4-times for " << i << std::endl;
1461 fPL[i] = 4.*fPL[i]; // increase parallelepiped
1462 t1=4.; // flag - that fPL was increased
1463 }
1464 }
1465 // cut step
1466 fDA[i] = fDA[i]*alambd;
1467 // expected function value change in next iteration
1468 fGT = fGT + fDA[i]*fGr[i];
1469 }
1470 }
1471 if (fDEBUG) {
1472 PrintVector("Reduced step",n,fDA);
1473 std::cout << "after applying step reduction of " << alambd << " expected function change is " << fGT << std::endl;
1474 }
1475
1476 //.. CHECK IF MINIMUM ATTAINED AND SET EXIT MODE
1477 // if expected fGT smaller than precision
1478 // and other stuff
1479 if (-fGT <= sp && t1 < 1. && alambd < 1.)fENDFLG = -1; // function is not decreasing
1480
1481 if (fENDFLG >= 0) {
1482 if (fAKAPPA < TMath::Abs(fEPS)) { // fit is converging
1483 if (fixFLG == 0)
1484 fENDFLG=1; // successful fit
1485 else {// we have fixed parameters
1486 if (fENDFLG == 0) {
1487 //... CHECK IF fiXING ON BOUND IS CORRECT
1488 fENDFLG = 1;
1489 fixFLG = 0;
1490 ifix1=-1;
1491 // release fixed parameters
1492 for( i = 0; i < fNpar; i++) fPL[i] = fPL0[i];
1493 fINDFLG[1] = 0;
1494 // and repeat iteration
1495 if (fDEBUG)
1496 std::cout << "We have fixed some params - released and repeat " << std::endl;
1497 goto L19;
1498 } else {
1499 if( ifix1 >= 0) {
1500 fi = fi + 1;
1501 fENDFLG = 0;
1502 }
1503 }
1504 }
1505 } else { // fit does not converge
1506 if( fixFLG != 0) {
1507 if( fi > fixFLG ) {
1508 //... CHECK IF fiXING ON BOUND IS CORRECT
1509 fENDFLG = 1;
1510 fixFLG = 0;
1511 ifix1=-1;
1512 for( i = 0; i < fNpar; i++) fPL[i] = fPL0[i];
1513 fINDFLG[1] = 0;
1514 goto L19;
1515 } else {
1516 fi = fi + 1;
1517 fENDFLG = 0;
1518 }
1519 } else {
1520 fi = fi + 1;
1521 fENDFLG = 0;
1522 }
1523 }
1524 }
1525
1526// L85:
1527 // iteration number limit is exceeded
1528 if(fENDFLG == 0 && nn3 >= fNmaxIter) fENDFLG=-3;
1529
1530 // fit errors are infinite;
1531 if(fENDFLG > 0 && fINDFLG[1] > 0) fENDFLG=-2;
1532
1533 //MONITO (fS,fNpar,nn3,IT,fEPS,fGT,fAKAPPA,alambd);
1534 if (fENDFLG == 0) { // make step
1535 for ( i = 0; i < n; i++) fA[i] = fA[i] + fDA[i];
1536 if (imax >= 0) fA[imax] = aiMAX;
1537 olds=fS;
1538 nn2=nn2+1;
1539 nn3=nn3+1;
1540 } else {
1541 // fill covariant matrix VL
1542 // fill parameter error matrix up
1543 Int_t il;
1544 il = 0;
1545 for( Int_t ip = 0; ip < fNpar; ip++) {
1546 if( fPL0[ip] > .0) {
1547 for( Int_t jp = 0; jp <= ip; jp++) {
1548 if(fPL0[jp] > .0) {
1549 // VL[ind(ip,jp)] = fZ[il];
1550 il = il + 1;
1551 }
1552 }
1553 }
1554 }
1555 return fENDFLG - 1;
1556 }
1557 if (fDEBUG)
1558 std::cout << "Continue and repeat iteration " << std::endl;
1559 goto L3;
1560}
1561
1562////////////////////////////////////////////////////////////////////////////////
1563/// Prints fit results.
1564///
1565/// ikode is the type of printing parameters
1566/// p is function value
1567///
1568/// - ikode = 1 - print values, errors and limits
1569/// - ikode = 2 - print values, errors and steps
1570/// - ikode = 3 - print values, errors, steps and derivatives
1571/// - ikode = 4 - print only values and errors
1572
1574{
1576 TString xsexpl="";
1577 TString colhdu[3],colhdl[3],cx2,cx3;
1578 switch (fENDFLG) {
1579 case 1:
1580 exitStatus="CONVERGED";
1581 break;
1582 case -1:
1583 exitStatus="CONST FCN";
1584 xsexpl="****\n* FUNCTION IS NOT DECREASING OR BAD DERIVATIVES\n****";
1585 break;
1586 case -2:
1587 exitStatus="ERRORS INF";
1588 xsexpl="****\n* ESTIMATED ERRORS ARE INfiNITE\n****";
1589 break;
1590 case -3:
1591 exitStatus="MAX ITER.";
1592 xsexpl="****\n* MAXIMUM NUMBER OF ITERATIONS IS EXCEEDED\n****";
1593 break;
1594 case -4:
1595 exitStatus="ZERO PROBAB";
1596 xsexpl="****\n* PROBABILITY OF LIKLIHOOD FUNCTION IS NEGATIVE OR ZERO\n****";
1597 break;
1598 default:
1599 exitStatus="UNDEfiNED";
1600 xsexpl="****\n* fiT IS IN PROGRESS\n****";
1601 break;
1602 }
1603 if (ikode == 1) {
1604 colhdu[0] = " ";
1605 colhdl[0] = " ERROR ";
1606 colhdu[1] = " PHYSICAL";
1607 colhdu[2] = " LIMITS ";
1608 colhdl[1] = " NEGATIVE ";
1609 colhdl[2] = " POSITIVE ";
1610 }
1611 if (ikode == 2) {
1612 colhdu[0] = " ";
1613 colhdl[0] = " ERROR ";
1614 colhdu[1] = " INTERNAL ";
1615 colhdl[1] = " STEP SIZE ";
1616 colhdu[2] = " INTERNAL ";
1617 colhdl[2] = " VALUE ";
1618 }
1619 if (ikode == 3) {
1620 colhdu[0] = " ";
1621 colhdl[0] = " ERROR ";
1622 colhdu[1] = " STEP ";
1623 colhdl[1] = " SIZE ";
1624 colhdu[2] = " fiRST ";
1625 colhdl[2] = " DERIVATIVE";
1626 }
1627 if (ikode == 4) {
1628 colhdu[0] = " PARABOLIC ";
1629 colhdl[0] = " ERROR ";
1630 colhdu[1] = " MINOS ";
1631 colhdu[2] = "ERRORS ";
1632 colhdl[1] = " NEGATIVE ";
1633 colhdl[2] = " POSITIVE ";
1634 }
1635 if(fENDFLG<1)Printf("%s", xsexpl.Data());
1636 Printf(" FCN=%g FROM FUMILI STATUS=%-10s %9d CALLS OF FCN",
1637 p,exitStatus.Data(),fNfcn);
1638 Printf(" EDM=%g ",-fGT);
1639 Printf(" EXT PARAMETER %-14s%-14s%-14s",
1640 (const char*)colhdu[0].Data()
1641 ,(const char*)colhdu[1].Data()
1642 ,(const char*)colhdu[2].Data());
1643 Printf(" NO. NAME VALUE %-14s%-14s%-14s",
1644 (const char*)colhdl[0].Data()
1645 ,(const char*)colhdl[1].Data()
1646 ,(const char*)colhdl[2].Data());
1647
1648 for (Int_t i=0;i<fNpar;i++) {
1649 if (ikode==3) {
1650 cx2 = Form("%14.5e",fDA[i]);
1651 cx3 = Form("%14.5e",fGr[i]);
1652
1653 }
1654 if (ikode==1) {
1655 cx2 = Form("%14.5e",fAMN[i]);
1656 cx3 = Form("%14.5e",fAMX[i]);
1657 }
1658 if (ikode==2) {
1659 cx2 = Form("%14.5e",fDA[i]);
1660 cx3 = Form("%14.5e",fA[i]);
1661 }
1662 if(ikode==4){
1663 cx2 = " *undefined* ";
1664 cx3 = " *undefined* ";
1665 }
1666 if(fPL0[i]<=0.) { cx2=" *fixed* ";cx3=""; }
1667 Printf("%4d %-11s%14.5e%14.5e%-14s%-14s",i+1
1668 ,fANames[i].Data(),fA[i],fParamError[i]
1669 ,cx2.Data(),cx3.Data());
1670 }
1671}
1672
1673////////////////////////////////////////////////////////////////////////////////
1674/// Releases parameter number ipar
1675
1677 if(ipar>=0 && ipar<fNpar && fPL0[ipar]<=0.) {
1678 fPL0[ipar] = -fPL0[ipar];
1679 if (fPL0[ipar] == 0. || fPL0[ipar]>=1.) fPL0[ipar]=.1;
1680 }
1681}
1682
1683////////////////////////////////////////////////////////////////////////////////
1684/// Sets pointer to data array provided by user.
1685/// Necessary if SetFCN is not called.
1686///
1687/// - numpoints: number of experimental points
1688/// - vecsize: size of data point vector + 2
1689/// (for N-dimensional fit vecsize=N+2)
1690/// - exdata: data array with following format
1691///
1692/// - exdata[0] = ExpValue_0 - experimental data value number 0
1693/// - exdata[1] = ExpSigma_0 - error of value number 0
1694/// - exdata[2] = X_0[0]
1695/// - exdata[3] = X_0[1]
1696///
1697/// - exdata[vecsize-1] = X_0[vecsize-3]
1698/// - exdata[vecsize] = ExpValue_1
1699/// - exdata[vecsize+1] = ExpSigma_1
1700/// - exdata[vecsize+2] = X_1[0]
1701///
1702/// - exdata[vecsize*(numpoints-1)] = ExpValue_(numpoints-1)
1703///
1704/// - exdata[vecsize*numpoints-1] = X_(numpoints-1)[vecsize-3]
1705
1713
1714
1715////////////////////////////////////////////////////////////////////////////////
1716/// ret fit method (chisquare or log-likelihood)
1717
1719{
1720 if (!strcmp(name,"H1FitChisquare")) SetFCN(H1FitChisquareFumili);
1721 if (!strcmp(name,"H1FitLikelihood")) SetFCN(H1FitLikelihoodFumili);
1722 if (!strcmp(name,"GraphFitChisquare")) SetFCN(GraphFitChisquareFumili);
1723}
1724
1725////////////////////////////////////////////////////////////////////////////////
1726/// Sets for parameter number ipar initial parameter value,
1727/// name parname, initial error verr and limits vlow and vhigh
1728/// - If vlow = vhigh but not equal to zero, parameter will be fixed.
1729/// - If vlow = vhigh = 0, parameter is released and its limits are discarded
1730
1732 if (ipar<0 || ipar>=fNpar) return -1;
1733 fANames[ipar] = parname;
1734 fA[ipar] = value;
1735 fParamError[ipar] = verr;
1736 if(vlow<vhigh) {
1737 fAMN[ipar] = vlow;
1738 fAMX[ipar] = vhigh;
1739 } else {
1740 if(vhigh<vlow) {
1741 fAMN[ipar] = vhigh;
1742 fAMX[ipar] = vlow;
1743 }
1744 if(vhigh==vlow) {
1745 if(vhigh==0.) {
1746 ReleaseParameter(ipar);
1747 fAMN[ipar] = gMINDOUBLE;
1748 fAMX[ipar] = gMAXDOUBLE;
1749 }
1750 if(vlow!=0) FixParameter(ipar);
1751 }
1752 }
1753 return 0;
1754}
1755
1756////////////////////////////////////////////////////////////////////////////////
1757/// Evaluates objective function ( chi-square ), gradients and
1758/// Z-matrix using data provided by user via TFumili::SetData
1759
1761{
1762 fS = 0.;
1763 Int_t i,j,l,k2=1,k1,ki=0;
1764 Double_t *x = new Double_t[fNED2];
1765 Double_t *df = new Double_t[fNpar];
1766 Int_t nx = fNED2-2;
1767 for (l=0;l<fNED1;l++) { // cycle on all exp. points
1768 k1 = k2;
1769 if (fLogLike) {
1771 nx = fNED2;
1772 k1 -= 2;
1773 }
1774
1775 for (i=0;i<nx;i++){
1776 ki += 1+i;
1777 x[i] = fEXDA[ki];
1778 }
1779 // Double_t y = ARITHM(df,x);
1780 Double_t y = EvalTFN(df,x);
1782 Double_t sig=1.;
1783 if(fLogLike) { // Likelihood method
1784 if(y>0.) {
1785 fS = fS - log(y);
1786 y = -y;
1787 sig= y;
1788 } else { //
1789 delete [] x;
1790 delete [] df;
1791 fS = 1e10;
1792 return -1; // indflg[0] = 1;
1793 }
1794 } else { // Chi2 method
1795 sig = fEXDA[k2]; // sigma of experimental point
1796 y = y - fEXDA[k1-1]; // f(x_i) - F_i
1797 fS = fS + (y*y/(sig*sig))*.5; // simple chi2/2
1798 }
1799 Int_t n = 0;
1800 for (i=0;i<fNpar;i++) {
1801 if (fPL0[i]>0){
1802 df[n] = df[i]/sig; // left only non-fixed param derivatives div by Sig
1803 fGr[i] += df[n]*(y/sig);
1804 n++;
1805 }
1806 }
1807 l = 0;
1808 for (i=0;i<n;i++)
1809 for (j=0;j<=i;j++)
1810 fZ[l++] += df[i]*df[j];
1811 k2 += fNED2;
1812 }
1813
1814 delete[] df;
1815 delete[] x;
1816 return 1;
1817}
1818
1819
1820////////////////////////////////////////////////////////////////////////////////
1821/// Minimization function for H1s using a Chisquare method.
1822/// Default method (function evaluated at center of bin)
1823/// for each point the cache contains the following info
1824/// - 1D : bc,e,xc (bin content, error, x of center of bin)
1825/// - 2D : bc,e,xc,yc
1826/// - 3D : bc,e,xc,yc,zc
1827
1829{
1831 if (fitOption.Integral) {
1833 return;
1834 }
1835 Double_t cu,eu,fu,fsum;
1836 Double_t x[3];
1837 Double_t *zik=nullptr;
1838 Double_t *pl0=nullptr;
1839
1840 TH1 *hfit = (TH1*)GetObjectFit();
1841 TF1 *f1 = (TF1*)GetUserFunc();
1842 Int_t nd = hfit->GetDimension();
1843 Int_t j;
1844
1845 npar = f1->GetNpar();
1847 if(flag == 9) return;
1848 zik = GetZ();
1849 pl0 = GetPL0();
1850
1851 Double_t *df = new Double_t[npar];
1852 f1->InitArgs(x,u);
1853 f = 0;
1854
1855 Int_t npfit = 0;
1856 Double_t *cache = fCache;
1857 for (Int_t i=0;i<fNpoints;i++) {
1858 if (nd > 2) x[2] = cache[4];
1859 if (nd > 1) x[1] = cache[3];
1860 x[0] = cache[2];
1861 cu = cache[0];
1863 fu = f1->EvalPar(x,u);
1864 if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
1865 eu = cache[1];
1866 Derivatives(df,x);
1867 Int_t n = 0;
1868 fsum = (fu-cu)/eu;
1869 if (flag!=1) {
1870 for (j=0;j<npar;j++) {
1871 if (pl0[j]>0) {
1872 df[n] = df[j]/eu;
1873 // left only non-fixed param derivatives / by Sigma
1874 gin[j] += df[n]*fsum;
1875 n++;
1876 }
1877 }
1878 Int_t l = 0;
1879 for (j=0;j<n;j++)
1880 for (Int_t k=0;k<=j;k++)
1881 zik[l++] += df[j]*df[k];
1882 }
1883 f += .5*fsum*fsum;
1884 npfit++;
1885 cache += fPointSize;
1886 }
1888 delete [] df;
1889}
1890
1891////////////////////////////////////////////////////////////////////////////////
1892/// Minimization function for H1s using a Chisquare method.
1893/// The "I"ntegral method is used
1894/// for each point the cache contains the following info
1895/// - 1D : bc,e,xc,xw (bin content, error, x of center of bin, x bin width of bin)
1896/// - 2D : bc,e,xc,xw,yc,yw
1897/// - 3D : bc,e,xc,xw,yc,yw,zc,zw
1898
1900{
1901 Double_t cu,eu,fu,fsum;
1902 Double_t x[3];
1903 Double_t *zik=nullptr;
1904 Double_t *pl0=nullptr;
1905
1906 TH1 *hfit = (TH1*)GetObjectFit();
1907 TF1 *f1 = (TF1*)GetUserFunc();
1908 Int_t nd = hfit->GetDimension();
1909 Int_t j;
1910
1911 f1->InitArgs(x,u);
1912 npar = f1->GetNpar();
1914 if(flag == 9) return;
1915 zik = GetZ();
1916 pl0 = GetPL0();
1917
1918 Double_t *df=new Double_t[npar];
1919 f = 0;
1920
1921 Int_t npfit = 0;
1922 Double_t *cache = fCache;
1923 for (Int_t i=0;i<fNpoints;i++) {
1924 cu = cache[0];
1926 f1->SetParameters(u);
1927 if (nd < 2) {
1928 fu = f1->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3])/cache[3];
1929 } else if (nd < 3) {
1930 fu = ((TF2*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5])/(cache[3]*cache[5]);
1931 } else {
1932 fu = ((TF3*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5],cache[6] - 0.5*cache[7],cache[6] + 0.5*cache[7])/(cache[3]*cache[5]*cache[7]);
1933 }
1934 if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
1935 eu = cache[1];
1936 Derivatives(df,x);
1937 Int_t n = 0;
1938 fsum = (fu-cu)/eu;
1939 if (flag!=1) {
1940 for (j=0;j<npar;j++) {
1941 if (pl0[j]>0){
1942 df[n] = df[j]/eu;
1943 // left only non-fixed param derivatives / by Sigma
1944 gin[j] += df[n]*fsum;
1945 n++;
1946 }
1947 }
1948 Int_t l = 0;
1949 for (j=0;j<n;j++)
1950 for (Int_t k=0;k<=j;k++)
1951 zik[l++] += df[j]*df[k];
1952 }
1953 f += .5*fsum*fsum;
1954 npfit++;
1955 cache += fPointSize;
1956 }
1958 delete[] df;
1959}
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Minimization function for H1s using a Likelihood method.
1963/// Basically, it forms the likelihood by determining the Poisson
1964/// probability that given a number of entries in a particular bin,
1965/// the fit would predict it's value. This is then done for each bin,
1966/// and the sum of the logs is taken as the likelihood.
1967///
1968/// Default method (function evaluated at center of bin)
1969/// for each point the cache contains the following info
1970/// - 1D : bc,e,xc (bin content, error, x of center of bin)
1971/// - 2D : bc,e,xc,yc
1972/// - 3D : bc,e,xc,yc,zc
1973
1975{
1977 if (fitOption.Integral) {
1979 return;
1980 }
1982 Double_t dersum[100];
1983 Double_t x[3];
1984 Int_t icu;
1985
1986 TH1 *hfit = (TH1*)GetObjectFit();
1987 TF1 *f1 = (TF1*)GetUserFunc();
1988 Int_t nd = hfit->GetDimension();
1989 Int_t j;
1990 Double_t *zik = GetZ();
1991 Double_t *pl0 = GetPL0();
1992
1993 npar = f1->GetNpar();
1995 if(flag == 9) return;
1996 Double_t *df=new Double_t[npar];
1997 if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
1998 f1->InitArgs(x,u);
1999 f = 0;
2000
2001 Int_t npfit = 0;
2002 Double_t *cache = fCache;
2003 for (Int_t i=0;i<fNpoints;i++) {
2004 if (nd > 2) x[2] = cache[4];
2005 if (nd > 1) x[1] = cache[3];
2006 x[0] = cache[2];
2007 cu = cache[0];
2009 fu = f1->EvalPar(x,u);
2010 if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
2011 if (flag == 2) {
2012 for (j=0;j<npar;j++) {
2013 dersum[j] += 1; //should be the derivative
2014 //grad[j] += dersum[j]*(fu-cu)/eu; dersum[j] = 0;
2015 }
2016 }
2017 if (fu < 1.e-9) fu = 1.e-9;
2018 icu = Int_t(cu);
2019 fsub = -fu +icu*TMath::Log(fu);
2020 fobs = GetSumLog(icu);
2021 fsub -= fobs;
2022 Derivatives(df,x);
2023 int n=0;
2024 // Here we need gradients of Log likelihood function
2025 //
2026 for (j=0;j<npar;j++) {
2027 if (pl0[j]>0){
2028 df[n] = df[j]*(icu/fu-1);
2029 gin[j] -= df[n];
2030 n++;
2031 }
2032 }
2033 Int_t l = 0;
2034 // Z-matrix here - production of first derivatives
2035 // of log-likelihood function
2036 for (j=0;j<n;j++)
2037 for (Int_t k=0;k<=j;k++)
2038 zik[l++] += df[j]*df[k];
2039
2040 f -= fsub;
2041 npfit++;
2042 cache += fPointSize;
2043 }
2044 f *= 2;
2046 delete[] df;
2047}
2048
2049////////////////////////////////////////////////////////////////////////////////
2050/// Minimization function for H1s using a Likelihood method.
2051/// Basically, it forms the likelihood by determining the Poisson
2052/// probability that given a number of entries in a particular bin,
2053/// the fit would predict it's value. This is then done for each bin,
2054/// and the sum of the logs is taken as the likelihood.
2055///
2056/// The "I"ntegral method is used
2057/// for each point the cache contains the following info
2058/// - 1D : bc,e,xc,xw (bin content, error, x of center of bin, x bin width of bin)
2059/// - 2D : bc,e,xc,xw,yc,yw
2060/// - 3D : bc,e,xc,xw,yc,yw,zc,zw
2061
2063{
2065 Double_t dersum[100];
2066 Double_t x[3];
2067 Int_t icu;
2068
2069 TH1 *hfit = (TH1*)GetObjectFit();
2070 TF1 *f1 = (TF1*)GetUserFunc();
2071 Int_t nd = hfit->GetDimension();
2072 Int_t j;
2073 Double_t *zik = GetZ();
2074 Double_t *pl0 = GetPL0();
2075
2076 Double_t *df=new Double_t[npar];
2077
2078 npar = f1->GetNpar();
2080 if(flag == 9) {delete [] df; return;}
2081 if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
2082 f1->InitArgs(x,u);
2083 f = 0;
2084
2085 Int_t npfit = 0;
2086 Double_t *cache = fCache;
2087 for (Int_t i=0;i<fNpoints;i++) {
2088 if (nd > 2) x[2] = cache[4];
2089 if (nd > 1) x[1] = cache[3];
2090 x[0] = cache[2];
2091 cu = cache[0];
2093 if (nd < 2) {
2094 fu = f1->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3])/cache[3];
2095 } else if (nd < 3) {
2096 fu = ((TF2*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5])/(cache[3]*cache[5]);
2097 } else {
2098 fu = ((TF3*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5],cache[6] - 0.5*cache[7],cache[6] + 0.5*cache[7])/(cache[3]*cache[5]*cache[7]);
2099 }
2100 if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
2101 if (flag == 2) {
2102 for (j=0;j<npar;j++) {
2103 dersum[j] += 1; //should be the derivative
2104 //grad[j] += dersum[j]*(fu-cu)/eu; dersum[j] = 0;
2105 }
2106 }
2107 if (fu < 1.e-9) fu = 1.e-9;
2108 icu = Int_t(cu);
2109 fsub = -fu +icu*TMath::Log(fu);
2110 fobs = GetSumLog(icu);
2111 fsub -= fobs;
2112 Derivatives(df,x);
2113 int n=0;
2114 // Here we need gradients of Log likelihood function
2115 //
2116 for (j=0;j<npar;j++) {
2117 if (pl0[j]>0){
2118 df[n] = df[j]*(icu/fu-1);
2119 gin[j] -= df[n];
2120 n++;
2121 }
2122 }
2123 Int_t l = 0;
2124 // Z-matrix here - production of first derivatives
2125 // of log-likelihood function
2126 for (j=0;j<n;j++)
2127 for (Int_t k=0;k<=j;k++)
2128 zik[l++] += df[j]*df[k];
2129
2130 f -= fsub;
2131 npfit++;
2132 cache += fPointSize;
2133 }
2134 f *= 2;
2136 delete[] df;
2137}
2138
2139
2140//______________________________________________________________________________
2141//
2142// STATIC functions
2143//______________________________________________________________________________
2144
2145////////////////////////////////////////////////////////////////////////////////
2146/// Minimization function for H1s using a Chisquare method.
2147
2153
2154////////////////////////////////////////////////////////////////////////////////
2155/// Minimization function for H1s using a Likelihood method.
2156/// Basically, it forms the likelihood by determining the Poisson
2157/// probability that given a number of entries in a particular bin,
2158/// the fit would predict it's value. This is then done for each bin,
2159/// and the sum of the logs is taken as the likelihood.
2160/// PDF: P=exp(-f(x_i))/[F_i]!*(f(x_i))^[F_i]
2161/// where F_i - experimental value, f(x_i) - expected theoretical value
2162/// [F_i] - integer part of F_i.
2163/// drawback is that if F_i>Int_t - GetSumLog will fail
2164/// for big F_i is faster to use Euler's Gamma-function
2165
2172
2173////////////////////////////////////////////////////////////////////////////////
2174/// Minimization function for Graphs using a Chisquare method.
2175/// In case of a TGraphErrors object, ex, the error along x, is projected
2176/// along the y-direction by calculating the function at the points x-exlow and
2177/// x+exhigh.
2178///
2179/// The chisquare is computed as the sum of the quantity below at each point:
2180///
2181/// (y - f(x))**2
2182/// -----------------------------------
2183/// ey**2 + (0.5*(exl + exh)*f'(x))**2
2184///
2185/// where x and y are the point coordinates and f'(x) is the derivative of function f(x).
2186/// This method to approximate the uncertainty in y because of the errors in x, is called
2187/// "effective variance" method.
2188/// The improvement, compared to the previously used method (f(x+ exhigh) - f(x-exlow))/2
2189/// is of (error of x)**2 order.
2190///
2191/// NOTE:
2192///
2193/// 1. By using the "effective variance" method a simple linear regression
2194/// becomes a non-linear case , which takes several iterations
2195/// instead of 0 as in the linear case .
2196///
2197/// 2. The effective variance technique assumes that there is no correlation
2198/// between the x and y coordinate .
2199///
2200/// In case the function lies below (above) the data point, ey is ey_low (ey_high).
2201
2203 Double_t *u, Int_t flag)
2204{
2206 Double_t x[1];
2207 Int_t i, bin, npfits=0;
2208
2210 TGraph *gr = (TGraph*)grFitter->GetObjectFit();
2211 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
2212 Foption_t fitOption = grFitter->GetFitOption();
2213
2214 Int_t n = gr->GetN();
2215 Double_t *gx = gr->GetX();
2216 Double_t *gy = gr->GetY();
2217 npar = f1->GetNpar();
2218
2219 grFitter->SetParNumber(npar);
2220
2221 if(flag == 9) return;
2222 Double_t *zik = grFitter->GetZ();
2223 Double_t *pl0 = grFitter->GetPL0();
2224 Double_t *df = new Double_t[npar];
2225
2226
2227 f1->InitArgs(x,u);
2228 f = 0;
2229 for (bin=0;bin<n;bin++) {
2230 x[0] = gx[bin];
2231 if (!f1->IsInside(x)) continue;
2232 cu = gy[bin];
2234 fu = f1->EvalPar(x,u);
2235 if (TF1::RejectedPoint()) continue;
2236 npfits++;
2237 Double_t eusq=1.;
2238 if (fitOption.W1) {
2239 eu = 1.;
2240 } else {
2241 exh = gr->GetErrorXhigh(bin);
2242 exl = gr->GetErrorXlow(bin);
2243 ey = gr->GetErrorY(bin);
2244 if (exl < 0) exl = 0;
2245 if (exh < 0) exh = 0;
2246 if (ey < 0) ey = 0;
2247 if (exh > 0 && exl > 0) {
2248// "Effective variance" method for projecting errors
2249 eux = 0.5*(exl + exh)*f1->Derivative(x[0], u);
2250 } else
2251 eux = 0.;
2252 eu = ey*ey+eux*eux;
2253 if (eu <= 0) eu = 1;
2254 eusq = TMath::Sqrt(eu);
2255 }
2256 grFitter->Derivatives(df,x);
2257 n = 0;
2258 fsum = (fu-cu)/eusq;
2259 for (i=0;i<npar;i++) {
2260 if (pl0[i]>0){
2261 df[n] = df[i]/eusq;
2262 // left only non-fixed param derivatives / by Sigma
2263 gin[i] += df[n]*fsum;
2264 n++;
2265 }
2266 }
2267 Int_t l = 0;
2268 for (i=0;i<n;i++)
2269 for (Int_t j=0;j<=i;j++)
2270 zik[l++] += df[i]*df[j];
2271 f += .5*fsum*fsum;
2272
2273 }
2274 delete [] df;
2276}
2277
#define d(i)
Definition RSha256.hxx:102
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
#define X(type, name)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
static const Double_t gMAXDOUBLE
Definition TFumili.cxx:125
void H1FitChisquareFumili(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Chisquare method.
Definition TFumili.cxx:2148
void PrintMatrix(const char *name, int n, double *x)
Definition TFumili.cxx:1078
void GraphFitChisquareFumili(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for Graphs using a Chisquare method.
Definition TFumili.cxx:2202
TFumili * gFumili
Definition TFumili.cxx:122
void H1FitLikelihoodFumili(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Likelihood method.
Definition TFumili.cxx:2166
static const Double_t gMINDOUBLE
Definition TFumili.cxx:126
void PrintVector(const char *name, int n, double *x)
Definition TFumili.cxx:1071
R__EXTERN TFumili * gFumili
Definition TFumili.h:117
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
#define hi
#define gROOT
Definition TROOT.h:411
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
1-Dim function class
Definition TF1.h:182
static void RejectPoint(Bool_t reject=kTRUE)
Static function to set the global flag to reject points the fgRejectPoint global flag is tested by al...
Definition TF1.cxx:3699
virtual Double_t Derivative(Double_t x, Double_t *params=nullptr, Double_t epsilon=0.001) const
Returns the first derivative of the function at point x, computed by Richardson's extrapolation metho...
Definition TF1.cxx:1120
virtual Int_t GetNpar() const
Definition TF1.h:461
virtual Double_t Integral(Double_t a, Double_t b, Double_t epsrel=1.e-12)
IntegralOneDim or analytical integral.
Definition TF1.cxx:2556
virtual void SetNumberFitPoints(Int_t npfits)
Definition TF1.h:608
virtual void InitArgs(const Double_t *x, const Double_t *params)
Initialize parameters addresses.
Definition TF1.cxx:2507
virtual Double_t EvalPar(const Double_t *x, const Double_t *params=nullptr)
Evaluate function with given coordinates and parameters.
Definition TF1.cxx:1475
static Bool_t RejectedPoint()
See TF1::RejectPoint above.
Definition TF1.cxx:3708
virtual void SetParameters(const Double_t *params)
Definition TF1.h:633
virtual Bool_t IsInside(const Double_t *x) const
return kTRUE if the point is inside the function range
Definition TF1.h:582
A 2-Dim function with parameters.
Definition TF2.h:29
A 3-Dim function with parameters.
Definition TF3.h:28
Double_t GetParameter(Int_t ipar) const override
Return current value of parameter ipar.
Definition TFumili.cxx:836
Bool_t fWARN
warnings
Definition TFumili.h:29
Int_t fNED12
fNED1+fNED2
Definition TFumili.h:18
void DeleteArrays()
Deallocates memory. Called from destructor TFumili::~TFumili.
Definition TFumili.cxx:262
Bool_t fNumericDerivatives
Definition TFumili.h:32
Double_t GetParError(Int_t ipar) const override
Return error of parameter ipar.
Definition TFumili.cxx:827
Bool_t IsFixed(Int_t ipar) const override
Return kTRUE if parameter ipar is fixed, kFALSE otherwise)
Definition TFumili.cxx:1061
Int_t fNED2
K - Length of vector X plus 2 (for chi2)
Definition TFumili.h:17
Double_t GetCovarianceMatrixElement(Int_t i, Int_t j) const override
Return element i,j from the covariance matrix.
Definition TFumili.cxx:794
Int_t ExecuteCommand(const char *command, Double_t *args, Int_t nargs) override
Execute MINUIT commands.
Definition TFumili.cxx:392
Int_t fNpar
fNpar - number of parameters
Definition TFumili.h:19
void PrintResults(Int_t k, Double_t p) const override
Prints fit results.
Definition TFumili.cxx:1573
Int_t GetNumberFreeParameters() const override
Return the number of free parameters.
Definition TFumili.cxx:815
Int_t GetNumberTotalParameters() const override
Return the total number of parameters (free + fixed)
Definition TFumili.cxx:807
Double_t * GetCovarianceMatrix() const override
Return a pointer to the covariance matrix.
Definition TFumili.cxx:785
virtual void FitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Likelihood method.
Definition TFumili.cxx:1974
~TFumili() override
TFumili destructor.
Definition TFumili.cxx:218
Int_t GetStats(Double_t &amin, Double_t &edm, Double_t &errdef, Int_t &nvpar, Int_t &nparx) const override
Return global fit parameters.
Definition TFumili.cxx:905
Double_t * fEXDA
[fNED12] experimental data poInt_ter
Definition TFumili.h:41
Int_t SGZ()
Evaluates objective function ( chi-square ), gradients and Z-matrix using data provided by user via T...
Definition TFumili.cxx:1760
void ReleaseParameter(Int_t ipar) override
Releases parameter number ipar.
Definition TFumili.cxx:1676
Int_t fNlog
Definition TFumili.h:14
virtual void FitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Chisquare method.
Definition TFumili.cxx:1828
const char * GetParName(Int_t ipar) const override
Return name of parameter ipar.
Definition TFumili.cxx:873
void FixParameter(Int_t ipar) override
Fixes parameter number ipar.
Definition TFumili.cxx:775
void Derivatives(Double_t *, Double_t *)
Calculates partial derivatives of theoretical function.
Definition TFumili.cxx:292
Double_t * fAMN
[fMaxParam] Minimum param value
Definition TFumili.h:51
TString * fANames
[fMaxParam] Parameter names
Definition TFumili.h:62
Double_t * GetPL0() const
Definition TFumili.h:95
Double_t * fPL
[fMaxParam] Limits for parameters step. If <0, then parameter is fixed
Definition TFumili.h:46
Int_t Eval(Int_t &npar, Double_t *grad, Double_t &fval, Double_t *par, Int_t flag)
Evaluate the minimisation function.
Definition TFumili.cxx:351
Int_t fMaxParam
Definition TFumili.h:13
void SetParNumber(Int_t ParNum)
Definition TFumili.cxx:169
void SetData(Double_t *, Int_t, Int_t)
Sets pointer to data array provided by user.
Definition TFumili.cxx:1706
Int_t fINDFLG[5]
internal flags;
Definition TFumili.h:25
Double_t EvalTFN(Double_t *, Double_t *)
Evaluate theoretical function.
Definition TFumili.cxx:363
Double_t * GetZ() const
Definition TFumili.h:102
Double_t * fParamError
[fMaxParam] Parameter errors
Definition TFumili.h:39
Double_t Chisquare(Int_t npar, Double_t *params) const override
return a chisquare equivalent
Definition TFumili.cxx:228
Int_t fENDFLG
End flag of fit.
Definition TFumili.h:24
Double_t * fR
[fMaxParam] Correlation factors
Definition TFumili.h:52
Double_t * fDA
[fMaxParam] Parameter step
Definition TFumili.h:49
void SetFitMethod(const char *name) override
ret fit method (chisquare or log-likelihood)
Definition TFumili.cxx:1718
Int_t fNstepDec
fNstepDec - maximum number of step decreasing counter
Definition TFumili.h:20
Int_t GetErrors(Int_t ipar, Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &globcc) const override
Return errors after MINOs not implemented.
Definition TFumili.cxx:883
Double_t * fZ0
[fMaxParam2] Matrix of approximate second derivatives of objective function This matrix is diagonal a...
Definition TFumili.h:34
Double_t * fPL0
[fMaxParam] Step initial bounds
Definition TFumili.h:45
Double_t * fA
[fMaxParam] Fit parameter array
Definition TFumili.h:44
Double_t fAKAPPA
Definition TFumili.h:60
Int_t Minimize()
Main minimization procedure.
Definition TFumili.cxx:1107
Int_t fNmaxIter
fNmaxIter - maximum number of iterations
Definition TFumili.h:22
TFumili(Int_t maxpar=25)
Definition TFumili.cxx:130
Int_t ExecuteSetCommand(Int_t)
Called from TFumili::ExecuteCommand in case of "SET xxx" and "SHOW xxx".
Definition TFumili.cxx:559
Double_t fS
fS - objective function value (return)
Definition TFumili.h:57
Double_t fEPS
fEPS - required precision of parameters. If fEPS<0 then
Definition TFumili.h:58
virtual void FitChisquareI(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Chisquare method.
Definition TFumili.cxx:1899
Int_t fNfcn
Number of FCN calls;.
Definition TFumili.h:15
Int_t fLastFixed
Last fixed parameter number.
Definition TFumili.h:23
void BuildArrays()
Allocates memory for internal arrays.
Definition TFumili.cxx:183
Double_t * fZ
[fMaxParam2] Inverse fZ0 matrix - covariance matrix
Definition TFumili.h:37
Bool_t fLogLike
LogLikelihood flag.
Definition TFumili.h:31
Int_t fNED1
Number of experimental vectors X=(x1,x2,...xK)
Definition TFumili.h:16
void Clear(Option_t *opt="") override
Resets all parameter names, values and errors to zero.
Definition TFumili.cxx:243
Double_t * fGr
[fMaxParam] Gradients of objective function
Definition TFumili.h:38
Double_t fGT
Expected function change in next iteration.
Definition TFumili.h:61
Int_t SetParameter(Int_t ipar, const char *parname, Double_t value, Double_t verr, Double_t vlow, Double_t vhigh) override
Sets for parameter number ipar initial parameter value, name parname, initial error verr and limits v...
Definition TFumili.cxx:1731
TString fCword
Command string.
Definition TFumili.h:63
virtual void FitLikelihoodI(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
Minimization function for H1s using a Likelihood method.
Definition TFumili.cxx:2062
Double_t fRP
Precision of fit ( machine zero on CDC 6000) quite old yeh?
Definition TFumili.h:59
Double_t * fCmPar
[fMaxParam] parameters of commands
Definition TFumili.h:55
Double_t * fDF
[fMaxParam] First derivatives of theoretical function
Definition TFumili.h:54
Double_t GetSumLog(Int_t) override
Return Sum(log(i) i=0,n used by log-likelihood fits.
Definition TFumili.cxx:922
Double_t * fSumLog
[fNlog]
Definition TFumili.h:40
Double_t * fAMX
[fMaxParam] Maximum param value
Definition TFumili.h:50
Bool_t fDEBUG
debug info
Definition TFumili.h:30
Int_t fNlimMul
fNlimMul - after fNlimMul successful iterations permits four-fold increasing of fPL
Definition TFumili.h:21
Bool_t fGRAD
user calculated gradients
Definition TFumili.h:28
void InvertZ(Int_t)
Inverts packed diagonal matrix Z by square-root method.
Definition TFumili.cxx:946
Double_t GetErrorY(Int_t bin) const override
It returns the error along Y at point i.
Double_t GetErrorXhigh(Int_t bin) const override
It returns the error along X at point i.
Double_t GetErrorXlow(Int_t bin) const override
It returns the error along X at point i.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
Double_t * GetY() const
Definition TGraph.h:139
Int_t GetN() const
Definition TGraph.h:131
Double_t * GetX() const
Definition TGraph.h:138
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:78
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
void ToUpper()
Change string to upper case.
Definition TString.cxx:1202
Int_t fPointSize
Number of words per point in the cache.
virtual TObject * GetObjectFit() const
TObject * fUserFunc
Pointer to user theoretical function (a TF1*)
virtual Foption_t GetFitOption() const
virtual void SetFCN(void(*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t))
To set the address of the minimization objective function called by the native compiler (see function...
Double_t * fCache
[fCacheSize] Array of points data (fNpoints*fPointSize < fCacheSize words)
void(* fFCN)(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
static TVirtualFitter * GetFitter()
static: return the current Fitter
virtual TObject * GetUserFunc() const
Int_t fNpoints
Number of points to fit.
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
TF1 * f1
Definition legend1.C:11
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124
TLine l
Definition textangle.C:4
auto * t1
Definition textangle.C:20