00001 // @(#)root/minuit2:$Id: FumiliGradientCalculator.cxx 20880 2007-11-19 11:23:41Z rdm $ 00002 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT * 00007 * * 00008 **********************************************************************/ 00009 00010 #include "Minuit2/FumiliGradientCalculator.h" 00011 #include "Minuit2/FumiliFCNBase.h" 00012 #include "Minuit2/MnUserTransformation.h" 00013 #include "Minuit2/FunctionGradient.h" 00014 #include "Minuit2/MinimumParameters.h" 00015 #include "Minuit2/FumiliChi2FCN.h" 00016 #include "Minuit2/FumiliMaximumLikelihoodFCN.h" 00017 00018 //to compare with N2P calculator 00019 //#define DEBUG 1 00020 #ifdef DEBUG 00021 #include "Minuit2/MnPrint.h" 00022 #include "Minuit2/Numerical2PGradientCalculator.h" 00023 #include "Minuit2/MnStrategy.h" 00024 #include "Minuit2/MnUserFcn.h" 00025 #endif 00026 00027 namespace ROOT { 00028 00029 namespace Minuit2 { 00030 00031 00032 FunctionGradient FumiliGradientCalculator::operator()(const MinimumParameters& par) const { 00033 00034 // Calculate gradient for Fumili using the gradient and Hessian provided by the FCN Fumili function 00035 // applying the external to int trasformation. 00036 00037 int nvar = par.Vec().size(); 00038 std::vector<double> extParam = fTransformation( par.Vec() ); 00039 // std::vector<double> deriv; 00040 // deriv.reserve( nvar ); 00041 // for (int i = 0; i < nvar; ++i) { 00042 // unsigned int ext = fTransformation.ExtOfInt(i); 00043 // if ( fTransformation.Parameter(ext).HasLimits()) 00044 // deriv.push_back( fTransformation.DInt2Ext( i, par.Vec()(i) ) ); 00045 // else 00046 // deriv.push_back(1.0); 00047 // } 00048 00049 // eval Gradient 00050 FumiliFCNBase & fcn = const_cast<FumiliFCNBase &>(fFcn); 00051 00052 fcn.EvaluateAll(extParam); 00053 00054 00055 MnAlgebraicVector v(nvar); 00056 MnAlgebraicSymMatrix h(nvar); 00057 00058 00059 const std::vector<double> & fcn_gradient = fFcn.Gradient(); 00060 assert( fcn_gradient.size() == extParam.size() ); 00061 00062 00063 // for (int i = 0; i < nvar; ++i) { 00064 // unsigned int iext = fTransformation.ExtOfInt(i); 00065 // double ideriv = 1.0; 00066 // if ( fTransformation.Parameter(iext).HasLimits()) 00067 // ideriv = fTransformation.DInt2Ext( i, par.Vec()(i) ) ; 00068 00069 00070 // // v(i) = fcn_gradient[iext]*deriv; 00071 // v(i) = ideriv*fcn_gradient[iext]; 00072 00073 // for (int j = i; j < nvar; ++j) { 00074 // unsigned int jext = fTransformation.ExtOfInt(j); 00075 // double jderiv = 1.0; 00076 // if ( fTransformation.Parameter(jext).HasLimits()) 00077 // jderiv = fTransformation.DInt2Ext( j, par.Vec()(j) ) ; 00078 00079 // // h(i,j) = deriv[i]*deriv[j]*fFcn.Hessian(iext,jext); 00080 // h(i,j) = ideriv*jderiv*fFcn.Hessian(iext,jext); 00081 // } 00082 // } 00083 00084 00085 // cache deriv and Index values . 00086 // in large Parameter limit then need to re-optimize and see if better not caching 00087 00088 std::vector<double> deriv(nvar); 00089 std::vector<unsigned int> extIndex(nvar); 00090 for (int i = 0; i < nvar; ++i) { 00091 extIndex[i] = fTransformation.ExtOfInt(i); 00092 deriv[i] = 1; 00093 if ( fTransformation.Parameter(extIndex[i]).HasLimits()) 00094 deriv[i] = fTransformation.DInt2Ext( i, par.Vec()(i) ) ; 00095 00096 v(i) = fcn_gradient[extIndex[i]]*deriv[i]; 00097 00098 for (int j = 0; j <= i; ++j) { 00099 h(i,j) = deriv[i]*deriv[j]*fFcn.Hessian(extIndex[i],extIndex[j]); 00100 } 00101 } 00102 00103 #ifdef DEBUG 00104 // compare with other Gradient 00105 // // calculate Gradient using Minuit method 00106 00107 Numerical2PGradientCalculator gc(MnUserFcn(fFcn,fTransformation), fTransformation, MnStrategy(1)); 00108 FunctionGradient g2 = gc(par); 00109 00110 std::cout << "Fumili Gradient " << v << std::endl; 00111 std::cout << "Minuit Gradient " << g2.Vec() << std::endl; 00112 #endif 00113 00114 // store calculated Hessian 00115 fHessian = h; 00116 return FunctionGradient(v); 00117 } 00118 00119 FunctionGradient FumiliGradientCalculator::operator()(const MinimumParameters& par, 00120 const FunctionGradient&) const 00121 00122 { 00123 // Needed for interface of base class. 00124 return this->operator()(par); 00125 00126 } 00127 00128 } // namespace Minuit2 00129 00130 } // namespace ROOT