package org.freehep.math.minuit; /** * * @version $Id: HessianGradientCalculator.java 8584 2006-08-10 23:06:37Z duns $ */ class HessianGradientCalculator implements GradientCalculator { HessianGradientCalculator(MnFcn fcn, MnUserTransformation par, MnStrategy stra) { theFcn= fcn; theTransformation = par; theStrategy = stra; } public FunctionGradient gradient(MinimumParameters par) { InitialGradientCalculator gc = new InitialGradientCalculator(theFcn, theTransformation, theStrategy); FunctionGradient gra = gc.gradient(par); return gradient(par, gra); } public FunctionGradient gradient(MinimumParameters par , FunctionGradient gradient) { return deltaGradient(par, gradient).first; } Pair<FunctionGradient, MnAlgebraicVector> deltaGradient(MinimumParameters par, FunctionGradient gradient) { if (!par.isValid()) throw new IllegalArgumentException("parameters are invalid"); MnAlgebraicVector x = par.vec().clone(); MnAlgebraicVector grd = gradient.grad().clone(); MnAlgebraicVector g2 = gradient.g2(); MnAlgebraicVector gstep = gradient.gstep(); double fcnmin = par.fval(); // std::cout<<"fval: "<<fcnmin<<std::endl; double dfmin = 4.*precision().eps2()*(Math.abs(fcnmin)+theFcn.errorDef()); int n = x.size(); MnAlgebraicVector dgrd = new MnAlgebraicVector(n); // initial starting values for(int i = 0; i < n; i++) { double xtf = x.get(i); double dmin = 4.*precision().eps2()*(xtf + precision().eps2()); double epspri = precision().eps2() + Math.abs(grd.get(i)*precision().eps2()); double optstp = Math.sqrt(dfmin/(Math.abs(g2.get(i))+epspri)); double d = 0.2*Math.abs(gstep.get(i)); if(d > optstp) d = optstp; if(d < dmin) d = dmin; double chgold = 10000.; double dgmin = 0.; double grdold = 0.; double grdnew = 0.; for(int j = 0; j < ncycle(); j++) { x.set(i, xtf + d); double fs1 = theFcn.valueOf(x); x.set(i, xtf - d); double fs2 = theFcn.valueOf(x); x.set(i, xtf); // double sag = 0.5*(fs1+fs2-2.*fcnmin); grdold = grd.get(i); grdnew = (fs1-fs2)/(2.*d); dgmin = precision().eps()*(Math.abs(fs1) + Math.abs(fs2))/d; if (Math.abs(grdnew) < precision().eps()) break; double change = Math.abs((grdold-grdnew)/grdnew); if(change > chgold && j > 1) break; chgold = change; grd.set(i, grdnew); if(change < 0.05) break; if( Math.abs(grdold-grdnew) < dgmin) break; if(d < dmin) break; d *= 0.2; } dgrd.set(i, Math.max(dgmin, Math.abs(grdold-grdnew))); } return new Pair<FunctionGradient, MnAlgebraicVector>(new FunctionGradient(grd, g2, gstep), dgrd); } MnFcn fcn() { return theFcn; } MnUserTransformation trafo() { return theTransformation; } MnMachinePrecision precision() { return theTransformation.precision(); } MnStrategy strategy() { return theStrategy; } int ncycle() { return strategy().hessianGradientNCycles(); } double stepTolerance() { return strategy().gradientStepTolerance(); } double gradTolerance() { return strategy().gradientTolerance(); } private MnFcn theFcn; private MnUserTransformation theTransformation; private MnStrategy theStrategy; }