35 #ifdef USE_FUMILI_FUNCTION
36 bool gUseFumiliFunction =
true;
46 template<
class MethodFunc>
47 class FumiliFunction :
public ROOT::Math::FitMethodFunction {
49 typedef ROOT::Math::FitMethodFunction::BaseFunction BaseFunction;
52 FumiliFunction(TFumili * fumili,
const ROOT::Math::FitMethodFunction * func) :
53 ROOT::Math::FitMethodFunction(func->NDim(), func->NPoints() ),
57 fObjFunc =
dynamic_cast<const MethodFunc *
>(func);
58 assert(fObjFunc != 0);
61 fModFunc =
new TF1(
"modfunc",ROOT::Math::ParamFunctor( &fObjFunc->ModelFunction() ) );
62 fFumili->SetUserFunc(fModFunc);
65 ROOT::Math::FitMethodFunction::Type_t Type()
const {
return fObjFunc->Type(); }
67 FumiliFunction * Clone()
const {
return new FumiliFunction(fFumili, fObjFunc); }
71 double DataElement(
const double * ,
unsigned int i,
double * g)
const {
76 unsigned int npar = fObjFunc->NDim();
79 const double *x = fObjFunc->Data().GetPoint(i,y,invError);
80 double fval = fFumili->EvalTFN(g,const_cast<double *>( x));
81 fFumili->Derivatives(g, const_cast<double *>( x));
83 if ( fObjFunc->Type() == ROOT::Math::FitMethodFunction::kLogLikelihood) {
84 double logPdf = y * ROOT::Math::Util::EvalLog( fval) - fval;
85 for (
unsigned int k = 0; k < npar; ++k) {
86 g[k] *= ( y/fval - 1.) ;
96 else if (fObjFunc->Type() == ROOT::Math::FitMethodFunction::kLeastSquare ) {
97 double resVal = (y-fval)*invError;
98 for (
unsigned int k = 0; k < npar; ++k) {
110 double DoEval(
const double *x )
const {
111 return (*fObjFunc)(x);
115 const MethodFunc * fObjFunc;
120 bool gUseFumiliFunction =
false;
134 ROOT::Math::FitMethodFunction * TFumiliMinimizer::fgFunc = 0;
135 ROOT::Math::FitMethodGradFunction * TFumiliMinimizer::fgGradFunc = 0;
136 TFumili * TFumiliMinimizer::fgFumili = 0;
139 ClassImp(TFumiliMinimizer);
142 TFumiliMinimizer::TFumiliMinimizer(
int ) :
152 #ifdef USE_STATIC_TMINUIT
154 if (fgFumili == 0) fgFumili =
new TFumili(0);
157 if (fFumili)
delete fFumili;
158 fFumili =
new TFumili(0);
165 TFumiliMinimizer::~TFumiliMinimizer()
168 if (fFumili)
delete fFumili;
171 TFumiliMinimizer::TFumiliMinimizer(
const TFumiliMinimizer &) :
177 TFumiliMinimizer & TFumiliMinimizer::operator = (
const TFumiliMinimizer &rhs)
180 if (
this == &rhs)
return *
this;
186 void TFumiliMinimizer::SetFunction(
const ROOT::Math::IMultiGenFunction & func) {
194 fFumili->SetParNumber(fDim);
197 const ROOT::Math::FitMethodFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodFunction *
>(&func);
199 Error(
"SetFunction",
"Wrong Fit method function type used for Fumili");
203 fgFunc =
const_cast<ROOT::Math::FitMethodFunction *
>(fcnfunc);
205 fFumili->SetFCN(&TFumiliMinimizer::Fcn);
207 #ifdef USE_FUMILI_FUNCTION
208 if (gUseFumiliFunction) {
209 if (fcnfunc->Type() == ROOT::Math::FitMethodFunction::kLogLikelihood)
210 fgFunc =
new FumiliFunction<ROOT::Fit::PoissonLikelihoodFCN<ROOT::Math::FitMethodFunction::BaseFunction> >(fFumili,fcnfunc);
211 else if (fcnfunc->Type() == ROOT::Math::FitMethodFunction::kLeastSquare)
212 fgFunc =
new FumiliFunction<ROOT::Fit::Chi2FCN<ROOT::Math::FitMethodFunction::BaseFunction> >(fFumili,fcnfunc);
218 void TFumiliMinimizer::SetFunction(
const ROOT::Math::IMultiGradFunction & func) {
224 fFumili->SetParNumber(fDim);
227 const ROOT::Math::FitMethodGradFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodGradFunction *
>(&func);
229 Error(
"SetFunction",
"Wrong Fit method function type used for Fumili");
234 fgGradFunc =
const_cast<ROOT::Math::FitMethodGradFunction *
>(fcnfunc);
235 fFumili->SetFCN(&TFumiliMinimizer::Fcn);
239 void TFumiliMinimizer::Fcn(
int & ,
double * g ,
double & f,
double * x ,
int ) {
242 f = TFumiliMinimizer::EvaluateFCN(const_cast<double*>(x),g);
258 double TFumiliMinimizer::EvaluateFCN(
const double * x,
double * grad) {
273 unsigned int ndata = 0;
274 unsigned int npar = 0;
276 ndata = fgFunc->NPoints();
277 npar = fgFunc->NDim();
278 fgFunc->UpdateNCalls();
280 else if (fgGradFunc) {
281 ndata = fgGradFunc->NPoints();
282 npar = fgGradFunc->NDim();
283 fgGradFunc->UpdateNCalls();
287 std::vector<double> gf(npar);
288 std::vector<double> hess(npar*(npar+1)/2);
291 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
298 std::cout <<
"=============================================";
299 std::cout <<
"par = ";
300 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
301 std::cout << x[ipar] <<
"\t";
302 std::cout << std::endl;
303 if (fgFunc) std::cout <<
"type " << fgFunc->Type() << std::endl;
309 if ( (fgFunc && fgFunc->Type() == ROOT::Math::FitMethodFunction::kLeastSquare) ||
310 (fgGradFunc && fgGradFunc->Type() == ROOT::Math::FitMethodGradFunction::kLeastSquare) ) {
313 for (
unsigned int i = 0; i < ndata; ++i) {
316 if (gUseFumiliFunction) {
317 fval = fgFunc->DataElement( x, i, &gf[0]);
321 fval = fgFunc->DataElement(x, i, &gf[0]);
323 fval = fgGradFunc->DataElement(x, i, &gf[0]);
331 for (
unsigned int j = 0; j < npar; ++j) {
332 grad[j] += fval * gf[j];
333 for (
unsigned int k = j; k < npar; ++ k) {
334 int idx = j + k*(k+1)/2;
335 hess[idx] += gf[j] * gf[k];
340 else if ( (fgFunc && fgFunc->Type() == ROOT::Math::FitMethodFunction::kLogLikelihood) ||
341 (fgGradFunc && fgGradFunc->Type() == ROOT::Math::FitMethodGradFunction::kLogLikelihood) ) {
349 for (
unsigned int i = 0; i < ndata; ++i) {
351 if (gUseFumiliFunction) {
352 fval = fgFunc->DataElement( x, i, &gf[0]);
357 fval = fgFunc->DataElement(x, i, &gf[0]);
359 fval = fgGradFunc->DataElement(x, i, &gf[0]);
367 for (
unsigned int j = 0; j < npar; ++j) {
370 for (
unsigned int k = j; k < npar; ++ k) {
371 int idx = j + k*(k+1)/2;
372 hess[idx] += gfj * gf[k];
378 Error(
"EvaluateFCN",
" type of fit method is not supported, it must be chi2 or log-likelihood");
383 double * zmatrix = fgFumili->GetZ();
384 double * pl0 = fgFumili->GetPL0();
385 assert(zmatrix != 0);
389 for (
unsigned int i = 0; i < npar; ++i) {
390 for (
unsigned int j = 0; j <= i; ++j) {
391 if (pl0[i] > 0 && pl0[j] > 0) {
392 zmatrix[l++] = hess[k];
399 std::cout <<
"FCN value " << sum <<
" grad ";
400 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
401 std::cout << grad[ipar] <<
"\t";
402 std::cout << std::endl << std::endl;
412 bool TFumiliMinimizer::SetVariable(
unsigned int ivar,
const std::string & name,
double val,
double step) {
415 Error(
"SetVariableValue",
"invalid TFumili pointer. Set function first ");
419 std::cout <<
"set variable " << ivar <<
" " << name <<
" value " << val <<
" step " << step << std::endl;
422 int ierr = fFumili->SetParameter(ivar , name.c_str(), val, step, 0., 0. );
424 Error(
"SetVariable",
"Error for parameter %d ",ivar);
430 bool TFumiliMinimizer::SetLimitedVariable(
unsigned int ivar,
const std::string & name,
double val,
double step,
double lower,
double upper) {
433 Error(
"SetVariableValue",
"invalid TFumili pointer. Set function first ");
437 std::cout <<
"set limited variable " << ivar <<
" " << name <<
" value " << val <<
" step " << step << std::endl;
439 int ierr = fFumili->SetParameter(ivar, name.c_str(), val, step, lower, upper );
441 Error(
"SetLimitedVariable",
"Error for parameter %d ",ivar);
447 bool Fumili2Minimizer::SetLowerLimitedVariable(
unsigned int ivar ,
const std::string & name ,
double val ,
double step ,
double lower ) {
449 double s = val-lower;
450 double upper = s*1.0E15;
451 if (s != 0) upper = 1.0E15;
452 return SetLimitedVariable(ivar, name, val, step, lower,upper);
457 bool TFumiliMinimizer::SetFixedVariable(
unsigned int ivar,
const std::string & name,
double val) {
460 Error(
"SetVariableValue",
"invalid TFumili pointer. Set function first ");
465 int ierr = fFumili->SetParameter(ivar, name.c_str(), val, 0., val, val );
466 fFumili->FixParameter(ivar);
469 std::cout <<
"Fix variable " << ivar <<
" " << name <<
" value " << std::endl;
473 Error(
"SetFixedVariable",
"Error for parameter %d ",ivar);
479 bool TFumiliMinimizer::SetVariableValue(
unsigned int ivar,
double val) {
482 Error(
"SetVariableValue",
"invalid TFumili pointer. Set function first ");
485 TString name = fFumili->GetParName(ivar);
486 double oldval, verr, vlow, vhigh = 0;
487 int ierr = fFumili->GetParameter( ivar, &name[0], oldval, verr, vlow, vhigh);
489 Error(
"SetVariableValue",
"Error for parameter %d ",ivar);
493 std::cout <<
"set variable " << ivar <<
" " << name <<
" value "
494 << val <<
" step " << verr << std::endl;
497 ierr = fFumili->SetParameter(ivar , name , val, verr, vlow, vhigh );
499 Error(
"SetVariableValue",
"Error for parameter %d ",ivar);
505 bool TFumiliMinimizer::Minimize() {
512 Error(
"SetVariableValue",
"invalid TFumili pointer. Set function first ");
526 int printlevel = PrintLevel();
532 if (printlevel == 0) fFumili->ExecuteCommand(
"SET NOW",arglist,0);
533 else fFumili->ExecuteCommand(
"SET WAR",arglist,0);
538 arglist[0] = MaxFunctionCalls();
539 arglist[1] = Tolerance();
542 std::cout <<
"Minimize using TFumili with tolerance = " << Tolerance()
543 <<
" max calls " << MaxFunctionCalls() << std::endl;
545 int iret = fFumili->ExecuteCommand(
"MIGRAD",arglist,2);
563 fFumili->GetStats(fMinVal,fEdm,errdef,nfree,ntot);
566 fFumili->PrintResults(printlevel,fMinVal);
569 assert (static_cast<unsigned int>(ntot) == fDim);
570 assert( nfree == fFumili->GetNumberFreeParameters() );
576 fParams.resize( fDim);
577 fErrors.resize( fDim);
578 fCovar.resize(fDim*fDim);
579 const double * cv = fFumili->GetCovarianceMatrix();
581 for (
unsigned int i = 0; i < fDim; ++i) {
582 fParams[i] = fFumili->GetParameter( i );
583 fErrors[i] = fFumili->GetParError( i );
585 if ( !fFumili->IsFixed(i) ) {
586 for (
unsigned int j = 0; j <=i ; ++j) {
587 if ( !fFumili->IsFixed(j) ) {
588 fCovar[i*fDim + j] = cv[l];
589 fCovar[j*fDim + i] = fCovar[i*fDim + j];
596 return (iret==0) ?
true :
false;