/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.minimization;
import org.apache.commons.lang.Validate;
import com.opengamma.analytics.math.MathException;
import com.opengamma.analytics.math.function.Function1D;
/**
*
*/
public class GoldenSectionMinimizer1D implements ScalarMinimizer {
private static final double GOLDEN = 0.61803399;
private static final MinimumBracketer BRACKETER = new ParabolicMinimumBracketer();
private static final int MAX_ITER = 10000;
private static final double EPS = 1e-12;
@Override
public double minimize(final Function1D<Double, Double> f, final double startPosition, final double lower, final double upper) {
return minimize(f, lower, upper);
}
public double minimize(final Function1D<Double, Double> f, final double lower, final double upper) {
Validate.notNull(f, "function");
double x0, x1, x2, x3, f1, f2, temp;
int i = 0;
final double[] triplet = BRACKETER.getBracketedPoints(f, lower, upper);
x0 = triplet[0];
x3 = triplet[2];
if (Math.abs(triplet[2] - triplet[1]) > Math.abs(triplet[1] - triplet[0])) {
x1 = triplet[1];
x2 = triplet[2] + GOLDEN * (triplet[1] - triplet[2]);
} else {
x2 = triplet[1];
x1 = triplet[0] + GOLDEN * (triplet[1] - triplet[0]);
}
f1 = f.evaluate(x1);
f2 = f.evaluate(x2);
while (Math.abs(x3 - x0) > EPS * (Math.abs(x1) + Math.abs(x2))) {
if (f2 < f1) {
temp = GOLDEN * (x2 - x3) + x3;
x0 = x1;
x1 = x2;
x2 = temp;
f1 = f2;
f2 = f.evaluate(temp);
} else {
temp = GOLDEN * (x1 - x0) + x0;
x3 = x2;
x2 = x1;
x1 = temp;
f2 = f1;
f1 = f.evaluate(temp);
}
i++;
if (i > MAX_ITER) {
throw new MathException("Could not find minimum: this should not happen because minimum should have been successfully bracketed");
}
}
if (f1 < f2) {
return x1;
}
return x2;
}
@Override
public Double minimize(final Function1D<Double, Double> function, final Double startPosition) {
throw new UnsupportedOperationException("Need lower and upper bounds to use this minimization method");
}
}