All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.finmath.optimizer.GoldenSectionSearch Maven / Gradle / Ivy

/*
 * (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
 *
 * Created on 25.01.2004
 */

package net.finmath.optimizer;

/**
 * This class implements a Golden Section search algorithm, i.e., a minimization,
 * implemented as a question-and-answer search algorithm.
 *
 * Example:
 * 
 * 
 * 		GoldenSectionSearch search = new GoldenSectionSearch(-1.0, 5.0);
 * 		while(search.getAccuracy() > 1E-11 && !search.isDone()) {
 * 			double x = search.getNextPoint();
 *
 * 			double y = (x - 0.656) * (x - 0.656);
 *
 * 			search.setValue(y);
 * 		}
 * 
 * 
* * For an example on how to use this class see also its main method. * * @author Christian Fries - http://www.christian-fries.de * @version 1.1 */ public class GoldenSectionSearch { // This is the golden section ratio public static final double GOLDEN_SECTION_RATIO = (3.0 - Math.sqrt(5.0)) / 2.0; // We store the left and right end point of the interval and a middle point (placed at golden section ratio) together with their values private final double[] points = new double[3]; // left, middle, right private final double[] values = new double[3]; // left, middle, right /* * State of solver */ private double nextPoint; // Stores the next point to return by getPoint() private boolean expectingValue = false; // Stores the state (true, if next call should be setValue(), false for getPoint()) private int numberOfIterations = 0; // Number of numberOfIterations private double accuracy; // Current accuracy of solution private boolean isDone = false; // Will be true if machine accuracy has been reached public static void main(final String[] args) { System.out.println("Test of GoldenSectionSearch Class.\n"); // Test 1 System.out.println("1. Find minimum of f(x) = (x - 0.656) * (x - 0.656):"); final GoldenSectionSearch search = new GoldenSectionSearch(-1.0, 5.0); while(search.getAccuracy() > 1E-11 && !search.isDone()) { final double x = search.getNextPoint(); final double y = (x - 0.656) * (x - 0.656); search.setValue(y); } System.out.println("Result....: " + search.getBestPoint()); System.out.println("Solution..: 0.656"); System.out.println("Iterations: " + search.getNumberOfIterations() + "\n"); // Test 2 System.out.println("2. Find minimum of f(x) = cos(x) on [0.0,6.0]:"); final GoldenSectionSearch search2 = new GoldenSectionSearch(0.0, 6.0); while(search2.getAccuracy() > 1E-11 && !search2.isDone()) { final double x = search2.getNextPoint(); final double y = Math.cos(x); search2.setValue(y); } System.out.println("Result....: " + search2.getBestPoint()); System.out.println("Solution..: " + Math.PI + " (Pi)"); System.out.println("Iterations: " + search2.getNumberOfIterations() + "\n"); } /** * @param leftPoint left point of search interval * @param rightPoint right point of search interval */ public GoldenSectionSearch(final double leftPoint, final double rightPoint) { super(); points[0] = leftPoint; points[1] = getGoldenSection(leftPoint, rightPoint); points[2] = rightPoint; nextPoint = points[0]; accuracy = points[2]-points[0]; } /** * @return Returns the best point obtained so far. */ public double getBestPoint() { // Lazy: we always return the middle point as best point return points[1]; } /** * Returns the next point for which a valuation is requested. * * @return Returns the next point for which a value should be set using setValue. */ public double getNextPoint() { expectingValue = true; return nextPoint; } /** * Set the value corresponding to the point returned by a previous call of getNextPoint(). * If setValue is called without prior call to getNextPoint(), * e.g., when called twice, a RuntimeException is thrown. * * @param value Value corresponding to point returned by previous getNextPoint() call. */ public void setValue(final double value) { if(!expectingValue) { throw new RuntimeException("Call to setValue() perfomed without prior getNextPoint() call (e.g. call performed twice)."); } if (numberOfIterations < 3) { /* * Initially fill values */ values[numberOfIterations] = value; if (numberOfIterations < 2) { nextPoint = points[numberOfIterations + 1]; } else { if (points[1] - points[0] > points[2] - points[1]) { nextPoint = getGoldenSection(points[0], points[1]); } else { nextPoint = getGoldenSection(points[1], points[2]); } } } else { /* * Golden section search update rule */ if (points[1] - points[0] > points[2] - points[1]) { // The left interval is the large one if (value < values[1]) { /* * Throw away right point */ points[2] = points[1]; values[2] = values[1]; points[1] = nextPoint; values[1] = value; } else { /* * Throw away left point */ points[0] = nextPoint; values[0] = value; } } else { // The right interval is the large one if (value < values[1]) { /* * Throw away left point */ points[0] = points[1]; values[0] = values[1]; points[1] = nextPoint; values[1] = value; } else { /* * Throw away right point */ points[2] = nextPoint; values[2] = value; } } /* * Update next point to ask value for (create point in larger interval) */ if (points[1] - points[0] > points[2] - points[1]) { nextPoint = getGoldenSection(points[0], points[1]); } else { nextPoint = getGoldenSection(points[1], points[2]); } /* * Save belt: check if still improve or if we have reached machine accuracy */ if(points[2]-points[0] >= accuracy) { isDone = true; } accuracy = points[2]-points[0]; } numberOfIterations++; expectingValue = false; } public GoldenSectionSearch optimize() { while(!isDone()) { final double parameter = getNextPoint(); final double value = value(parameter); this.setValue(value); } return this; } public double value(final double parameter) { // You need to overwrite this mehtod with you own objective function throw new RuntimeException("Objective function not overwritten."); } /** * Get the golden section of an interval as gs * left + (1-gs) * right, where * gs is GOLDEN_SECTION_RATIO. * * @param left Left point of the interval. * @param right Right point of the interval. * @return Returns the golden section of an interval. */ public static double getGoldenSection(final double left, final double right) { return GOLDEN_SECTION_RATIO * left + (1.0 - GOLDEN_SECTION_RATIO) * right; } /** * @return Returns the number of iterations needed so far. */ public int getNumberOfIterations() { return numberOfIterations; } /** * @return Returns the accuracy obtained so far. */ public double getAccuracy() { return accuracy; } /** * @return Returns true if the solver is unable to improve further. This may be either due to reached accuracy or due to no solution existing. */ public boolean isDone() { return isDone; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy