package org.geogebra.common.kernel.optimization; import org.apache.commons.math3.analysis.UnivariateFunction; import org.apache.commons.math3.optim.MaxEval; import org.apache.commons.math3.optim.nonlinear.scalar.GoalType; import org.apache.commons.math3.optim.univariate.BrentOptimizer; import org.apache.commons.math3.optim.univariate.SearchInterval; import org.apache.commons.math3.optim.univariate.UnivariateObjectiveFunction; import org.apache.commons.math3.optim.univariate.UnivariatePointValuePair; import org.geogebra.common.kernel.Kernel; /** * wrapper class for BrentOptimizer * */ public class ExtreumumFinderBrent implements ExtremumFinderI { final private static MaxEval MAX_EVALUATIONS = new MaxEval(100); private BrentOptimizer brentOptimizer; @SuppressWarnings("javadoc") public ExtreumumFinderBrent() { this.brentOptimizer = new BrentOptimizer(Kernel.STANDARD_PRECISION, Kernel.MAX_PRECISION); } private double findMinOrMax(double left, double right, UnivariateFunction distFun, double minPrecision, GoalType goalType) { brentOptimizer.setRelativePrecision(minPrecision); UnivariateObjectiveFunction fun = new UnivariateObjectiveFunction( distFun); UnivariatePointValuePair solution = brentOptimizer.optimize(fun, MAX_EVALUATIONS, goalType, new SearchInterval(left, right)); // if (GoalType.MINIMIZE.equals(goalType)) { // Log.error("value from old optimizer = " // + oldOptimizer.findMinimum(left, right, distFun, // minPrecision)); // } else { // Log.error("value from old optimizer = " + oldOptimizer // .findMaximum(left, right, distFun, minPrecision)); // // } // Log.error("value from new optimizer = " + solution.getPoint() + " " // + solution.getValue()); double ret = solution.getPoint(); double retVal = solution.getValue(); if (Double.isNaN(ret)) { return Double.NaN; } double leftVal = distFun.value(left); double rightVal = distFun.value(right); // check end points if (GoalType.MINIMIZE.equals(goalType)) { if (leftVal < retVal) { return leftVal; } if (rightVal < retVal) { return rightVal; } } else /* MAXIMIZE */ { if (leftVal > retVal) { return leftVal; } if (rightVal > retVal) { return rightVal; } } return ret; } public double findMinimum(double left, double right, UnivariateFunction distFun, double minPrecision) { return findMinOrMax(left, right, distFun, minPrecision, GoalType.MINIMIZE); } public double findMaximum(double left, double right, UnivariateFunction distFun, double minPrecision) { return findMinOrMax(left, right, distFun, minPrecision, GoalType.MAXIMIZE); } }