/* * File: LineBracketInterpolatorBrent.java * Authors: Kevin R. Dixon * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright Jun 17, 2008, Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the U.S. Government. * Export of this program may require a license from the United States * Government. See CopyrightHistory.txt for complete details. * */ package gov.sandia.cognition.learning.algorithm.minimization.line.interpolator; import gov.sandia.cognition.evaluator.Evaluator; import gov.sandia.cognition.learning.algorithm.minimization.line.LineBracket; /** * Implements Brent's method of function interpolation to find a minimum. * If the function is well behaved, then Brent uses non-slope-based parabolic * interpolation. Otherwise, Brent uses Golden-section and secant * interpolation. * @author Kevin R. Dixon * @since 2.1 */ public class LineBracketInterpolatorBrent extends AbstractLineBracketInterpolator<Evaluator<Double,Double>> { /** * Non-slope based parabolic interpolator. */ private LineBracketInterpolatorParabola parabolicInterpolator; /** * Golden-section step interpolator. */ private LineBracketInterpolatorGoldenSection goldenInterpolator; /** * Creates a new instance of LineBracketInterpolatorBrent */ public LineBracketInterpolatorBrent() { super( DEFAULT_TOLERANCE ); this.setGoldenInterpolator( new LineBracketInterpolatorGoldenSection() ); this.setParabolicInterpolator( new LineBracketInterpolatorParabola() ); } public double findMinimum( LineBracket bracket, double minx, double maxx, Evaluator<Double, Double> function ) { // We'd prefer using the parabolic interpolator, but only if // 1) We have enough points // 2) The function is well behaved // If these conditions aren't met, then use the Golden-Section step double nextX = Double.POSITIVE_INFINITY; boolean useGoldenSection; if( this.getParabolicInterpolator().hasSufficientPoints( bracket ) ) { try { nextX = this.getParabolicInterpolator().findMinimum( bracket, minx, maxx, function ); useGoldenSection = false; } // Parabolic interpolation failed... using Golden Section step instead. catch (IllegalArgumentException e) { useGoldenSection = true; } } else { useGoldenSection = true; } // If parabolic interpolation wasn't appropriate, then just use the // golden section step if( useGoldenSection ) { nextX = this.getGoldenInterpolator().findMinimum( bracket, minx, maxx, function ); } return nextX; } public boolean hasSufficientPoints( LineBracket bracket ) { return (bracket.getLowerBound() != null) && (bracket.getUpperBound() != null); } /** * Getter for parabolicInterpolator * @return * Non-slope based parabolic interpolator. */ public LineBracketInterpolatorParabola getParabolicInterpolator() { return this.parabolicInterpolator; } /** * Setter for parabolicInterpolator * @param parabolicInterpolator * Non-slope based parabolic interpolator. */ public void setParabolicInterpolator( LineBracketInterpolatorParabola parabolicInterpolator ) { this.parabolicInterpolator = parabolicInterpolator; } /** * Getter for goldenInterpolator * @return * Golden-section step interpolator. */ public LineBracketInterpolatorGoldenSection getGoldenInterpolator() { return this.goldenInterpolator; } /** * Setter for goldenInterpolator * @param goldenInterpolator * Golden-section step interpolator. */ public void setGoldenInterpolator( LineBracketInterpolatorGoldenSection goldenInterpolator ) { this.goldenInterpolator = goldenInterpolator; } }