00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Minuit2/HessianGradientCalculator.h"
00011 #include "Minuit2/InitialGradientCalculator.h"
00012 #include "Minuit2/MnFcn.h"
00013 #include "Minuit2/MnUserTransformation.h"
00014 #include "Minuit2/MnMachinePrecision.h"
00015 #include "Minuit2/MinimumParameters.h"
00016 #include "Minuit2/FunctionGradient.h"
00017 #include "Minuit2/MnStrategy.h"
00018
00019 #include <math.h>
00020
00021
00022
00023 #if defined(DEBUG) || defined(WARNINGMSG)
00024 #include "Minuit2/MnPrint.h"
00025 #endif
00026
00027 #include "Minuit2/MPIProcess.h"
00028
00029 namespace ROOT {
00030
00031 namespace Minuit2 {
00032
00033
00034 FunctionGradient HessianGradientCalculator::operator()(const MinimumParameters& par) const {
00035
00036 InitialGradientCalculator gc(fFcn, fTransformation, fStrategy);
00037 FunctionGradient gra = gc(par);
00038
00039 return (*this)(par, gra);
00040 }
00041
00042 FunctionGradient HessianGradientCalculator::operator()(const MinimumParameters& par, const FunctionGradient& Gradient) const {
00043
00044 std::pair<FunctionGradient, MnAlgebraicVector> mypair = DeltaGradient(par, Gradient);
00045
00046 return mypair.first;
00047 }
00048
00049 const MnMachinePrecision& HessianGradientCalculator::Precision() const {
00050
00051 return fTransformation.Precision();
00052 }
00053
00054 unsigned int HessianGradientCalculator::Ncycle() const {
00055
00056 return Strategy().HessianGradientNCycles();
00057 }
00058
00059 double HessianGradientCalculator::StepTolerance() const {
00060
00061 return Strategy().GradientStepTolerance();
00062 }
00063
00064 double HessianGradientCalculator::GradTolerance() const {
00065
00066 return Strategy().GradientTolerance();
00067 }
00068
00069 std::pair<FunctionGradient, MnAlgebraicVector> HessianGradientCalculator::DeltaGradient(const MinimumParameters& par, const FunctionGradient& Gradient) const {
00070
00071 assert(par.IsValid());
00072
00073 MnAlgebraicVector x = par.Vec();
00074 MnAlgebraicVector grd = Gradient.Grad();
00075 const MnAlgebraicVector& g2 = Gradient.G2();
00076
00077
00078 MnAlgebraicVector gstep = Gradient.Gstep();
00079
00080 double fcnmin = par.Fval();
00081
00082
00083 double dfmin = 4.*Precision().Eps2()*(fabs(fcnmin)+Fcn().Up());
00084
00085 unsigned int n = x.size();
00086 MnAlgebraicVector dgrd(n);
00087
00088 MPIProcess mpiproc(n,0);
00089
00090 unsigned int startElementIndex = mpiproc.StartElementIndex();
00091 unsigned int endElementIndex = mpiproc.EndElementIndex();
00092
00093 for(unsigned int i = startElementIndex; i < endElementIndex; i++) {
00094 double xtf = x(i);
00095 double dmin = 4.*Precision().Eps2()*(xtf + Precision().Eps2());
00096 double epspri = Precision().Eps2() + fabs(grd(i)*Precision().Eps2());
00097 double optstp = sqrt(dfmin/(fabs(g2(i))+epspri));
00098 double d = 0.2*fabs(gstep(i));
00099 if(d > optstp) d = optstp;
00100 if(d < dmin) d = dmin;
00101 double chgold = 10000.;
00102 double dgmin = 0.;
00103 double grdold = 0.;
00104 double grdnew = 0.;
00105 for(unsigned int j = 0; j < Ncycle(); j++) {
00106 x(i) = xtf + d;
00107 double fs1 = Fcn()(x);
00108 x(i) = xtf - d;
00109 double fs2 = Fcn()(x);
00110 x(i) = xtf;
00111
00112
00113
00114 grdold = grd(i);
00115 grdnew = (fs1-fs2)/(2.*d);
00116 dgmin = Precision().Eps()*(fabs(fs1) + fabs(fs2))/d;
00117
00118 if (grdnew == 0) break;
00119 double change = fabs((grdold-grdnew)/grdnew);
00120 if(change > chgold && j > 1) break;
00121 chgold = change;
00122 grd(i) = grdnew;
00123
00124 gstep(i) = d;
00125
00126 if(change < 0.05) break;
00127 if(fabs(grdold-grdnew) < dgmin) break;
00128 if(d < dmin) break;
00129 d *= 0.2;
00130 }
00131
00132 dgrd(i) = std::max(dgmin, fabs(grdold-grdnew));
00133
00134 #ifdef DEBUG
00135 std::cout << "HGC Param : " << i << "\t new g1 = " << grd(i) << " gstep = " << d << " dgrd = " << dgrd(i) << std::endl;
00136 #endif
00137
00138 }
00139
00140 mpiproc.SyncVector(grd);
00141 mpiproc.SyncVector(gstep);
00142 mpiproc.SyncVector(dgrd);
00143
00144 return std::pair<FunctionGradient, MnAlgebraicVector>(FunctionGradient(grd, g2, gstep), dgrd);
00145 }
00146
00147 }
00148
00149 }