package org.freehep.math.minuit; /** * * @version $Id: Numerical2PGradientCalculator.java 8584 2006-08-10 23:06:37Z duns $ */ class Numerical2PGradientCalculator implements GradientCalculator { Numerical2PGradientCalculator(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) { if (!par.isValid()) throw new IllegalArgumentException("Parameters are invalid"); MnAlgebraicVector x = par.vec().clone(); double fcnmin = par.fval(); double dfmin = 8.*precision().eps2()*(Math.abs(fcnmin)+theFcn.errorDef()); double vrysml = 8.*precision().eps()*precision().eps(); int n = x.size(); MnAlgebraicVector grd = gradient.grad().clone(); MnAlgebraicVector g2 = gradient.g2().clone(); MnAlgebraicVector gstep = gradient.gstep().clone(); for(int i = 0; i < n; i++) { double xtf = x.get(i); double epspri = precision().eps2() + Math.abs(grd.get(i)*precision().eps2()); double stepb4 = 0.; for(int j = 0; j < ncycle(); j++) { double optstp = Math.sqrt(dfmin/(Math.abs(g2.get(i))+epspri)); double step = Math.max(optstp, Math.abs(0.1*gstep.get(i))); if(trafo().parameter(trafo().extOfInt(i)).hasLimits()) { if(step > 0.5) step = 0.5; } double stpmax = 10.*Math.abs(gstep.get(i)); if(step > stpmax) step = stpmax; double stpmin = Math.max(vrysml, 8.*Math.abs(precision().eps2()*x.get(i))); if(step < stpmin) step = stpmin; if(Math.abs((step-stepb4)/step) < stepTolerance()) { break; } gstep.set(i,step); stepb4 = step; x.set(i,xtf + step); double fs1 = theFcn.valueOf(x); x.set(i,xtf - step); double fs2 = theFcn.valueOf(x); x.set(i,xtf); double grdb4 = grd.get(i); grd.set(i, 0.5*(fs1 - fs2)/step); g2.set(i, (fs1 + fs2 - 2.*fcnmin)/step/step); if(Math.abs(grdb4-grd.get(i))/(Math.abs(grd.get(i))+dfmin/step) < gradTolerance()) { break; } } } return new FunctionGradient(grd, g2, gstep); } MnFcn fcn() { return theFcn; } MnUserTransformation trafo() { return theTransformation; } MnMachinePrecision precision() { return theTransformation.precision(); } MnStrategy strategy() { return theStrategy; } int ncycle() { return strategy().gradientNCycles(); } double stepTolerance() { return strategy().gradientStepTolerance(); } double gradTolerance() { return strategy().gradientTolerance(); } private MnFcn theFcn; private MnUserTransformation theTransformation; private MnStrategy theStrategy; }