"PowellOptimizer": Added a constructor for setting of the absolute tolerance,

removed one redundant function evaluation.
Line search relative tolerance explicitly set in the optimizer instance
created in "PowellOptimizerTest".


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@982639 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2010-08-05 14:26:13 +00:00
parent 173735d2df
commit d402f6b5e1
2 changed files with 64 additions and 29 deletions

View File

@ -17,6 +17,8 @@
package org.apache.commons.math.optimization.general; package org.apache.commons.math.optimization.general;
import java.util.Arrays;
import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MaxIterationsExceededException; import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.UnivariateRealFunction;
@ -39,28 +41,49 @@ import org.apache.commons.math.optimization.univariate.BrentOptimizer;
public class PowellOptimizer public class PowellOptimizer
extends AbstractScalarOptimizer { extends AbstractScalarOptimizer {
/** /**
* Defautl line search tolerance ({@value}). * Default relative tolerance for line search ({@value}).
*/ */
public static final double DEFAULT_LINE_SEARCH_TOLERANCE = 1e-7; public static final double DEFAULT_LS_RELATIVE_TOLERANCE = 1e-7;
/**
* Default absolute tolerance for line search ({@value}).
*/
public static final double DEFAULT_LS_ABSOLUTE_TOLERANCE = 1e-11;
/** /**
* Line search. * Line search.
*/ */
private final LineSearch line; private final LineSearch line;
/** /**
* Constructor using the default line search tolerance (see the * Constructor with default line search tolerances (see the
* {@link #PowellOptimizer(double) other constructor}). * {@link #PowellOptimizer(double,double) other constructor}).
*/ */
public PowellOptimizer() { public PowellOptimizer() {
this(DEFAULT_LINE_SEARCH_TOLERANCE); this(DEFAULT_LS_RELATIVE_TOLERANCE,
DEFAULT_LS_ABSOLUTE_TOLERANCE);
} }
/** /**
* @param lineSearchTolerance Relative error tolerance for the line search * Constructor with default absolute line search tolerances (see
* algorithm ({@link BrentOptimizer}). * the {@link #PowellOptimizer(double,double) other constructor}).
*
* @param lsRelativeTolerance Relative error tolerance for
* the line search algorithm ({@link BrentOptimizer}).
*/ */
public PowellOptimizer(double lineSearchTolerance) { public PowellOptimizer(double lsRelativeTolerance) {
line = new LineSearch(lineSearchTolerance); this(lsRelativeTolerance,
DEFAULT_LS_ABSOLUTE_TOLERANCE);
}
/**
* @param lsRelativeTolerance Relative error tolerance for
* the line search algorithm ({@link BrentOptimizer}).
* @param lsAbsoluteTolerance Relative error tolerance for
* the line search algorithm ({@link BrentOptimizer}).
*/
public PowellOptimizer(double lsRelativeTolerance,
double lsAbsoluteTolerance) {
line = new LineSearch(lsRelativeTolerance,
lsAbsoluteTolerance);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -89,9 +112,9 @@ public class PowellOptimizer
int bigInd = 0; int bigInd = 0;
double alphaMin = 0; double alphaMin = 0;
double[] direc1 = new double[n]; double[] direc1 = null;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
direc1 = direc[i]; direc1 = Arrays.copyOf(direc[i], n);
fX2 = fVal; fX2 = fVal;
@ -188,11 +211,13 @@ public class PowellOptimizer
private double valueAtOptimum = Double.NaN; private double valueAtOptimum = Double.NaN;
/** /**
* @param tolerance Relative tolerance. * @param relativeTolerance Relative tolerance.
* @param absoluteTolerance Absolute tolerance.
*/ */
public LineSearch(double tolerance) { public LineSearch(double relativeTolerance,
optim.setRelativeAccuracy(tolerance); double absoluteTolerance) {
optim.setAbsoluteAccuracy(Math.ulp(1d)); optim.setRelativeAccuracy(relativeTolerance);
optim.setAbsoluteAccuracy(absoluteTolerance);
} }
/** /**
@ -206,6 +231,11 @@ public class PowellOptimizer
public void search(final double[] p, public void search(final double[] p,
final double[] d) final double[] d)
throws OptimizationException { throws OptimizationException {
// Reset.
optimum = Double.NaN;
valueAtOptimum = Double.NaN;
try { try {
final int n = p.length; final int n = p.length;
final UnivariateRealFunction f = new UnivariateRealFunction() { final UnivariateRealFunction f = new UnivariateRealFunction() {
@ -216,7 +246,8 @@ public class PowellOptimizer
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = p[i] + alpha * d[i]; x[i] = p[i] + alpha * d[i];
} }
return computeObjectiveValue(x); final double obj = computeObjectiveValue(x);
return obj;
} }
}; };
@ -226,7 +257,7 @@ public class PowellOptimizer
bracket.getLo(), bracket.getLo(),
bracket.getHi(), bracket.getHi(),
bracket.getMid()); bracket.getMid());
valueAtOptimum = f.value(optimum); valueAtOptimum = optim.getFunctionValue();
} catch (FunctionEvaluationException e) { } catch (FunctionEvaluationException e) {
throw new OptimizationException(e); throw new OptimizationException(e);
} catch (MaxIterationsExceededException e) { } catch (MaxIterationsExceededException e) {

View File

@ -36,7 +36,7 @@ public class PowellOptimizerTest {
public void testSumSinc() throws MathException { public void testSumSinc() throws MathException {
final MultivariateRealFunction func = new SumSincFunction(-1); final MultivariateRealFunction func = new SumSincFunction(-1);
int dim = 10; int dim = 2;
final double[] minPoint = new double[dim]; final double[] minPoint = new double[dim];
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
minPoint[i] = 0; minPoint[i] = 0;
@ -48,13 +48,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = minPoint[i]; init[i] = minPoint[i];
} }
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7); // doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
// Initial is far from minimum. // Initial is far from minimum.
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = minPoint[i] + 3; init[i] = minPoint[i] + 3;
} }
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7); doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
} }
@Test @Test
@ -80,13 +80,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = minPoint[i]; init[i] = minPoint[i];
} }
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8); doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
// Initial is far from minimum. // Initial is far from minimum.
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = minPoint[i] - 20; init[i] = minPoint[i] - 20;
} }
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8); doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
} }
@Test @Test
@ -112,13 +112,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = maxPoint[i]; init[i] = maxPoint[i];
} }
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8); doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
// Initial is far from minimum. // Initial is far from minimum.
for (int i = 0; i < dim; i++) { for (int i = 0; i < dim; i++) {
init[i] = maxPoint[i] - 20; init[i] = maxPoint[i] - 20;
} }
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8); doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
} }
/** /**
@ -126,18 +126,22 @@ public class PowellOptimizerTest {
* @param optimum Expected optimum. * @param optimum Expected optimum.
* @param init Starting point. * @param init Starting point.
* @param goal Minimization or maximization. * @param goal Minimization or maximization.
* @param objTol Tolerance (relative error on the objective function). * @param xTol Tolerance (relative error on the objective function) for
* @param pointTol Tolerance on the position of the optimum. * "Brent" line search algorithm used by "Powell".
* @param fTol Tolerance (relative error on the objective function) for
* "Powell" algorithm.
* @param pointTol Tolerance for checking that the optimum is correct.
*/ */
private void doTest(MultivariateRealFunction func, private void doTest(MultivariateRealFunction func,
double[] optimum, double[] optimum,
double[] init, double[] init,
GoalType goal, GoalType goal,
double objTol, double xTol,
double fTol,
double pointTol) double pointTol)
throws MathException { throws MathException {
final MultivariateRealOptimizer optim = new PowellOptimizer(); final MultivariateRealOptimizer optim = new PowellOptimizer(xTol);
optim.setConvergenceChecker(new SimpleScalarValueChecker(objTol, -1)); optim.setConvergenceChecker(new SimpleScalarValueChecker(fTol, -1));
final RealPointValuePair result = optim.optimize(func, goal, init); final RealPointValuePair result = optim.optimize(func, goal, init);
final double[] found = result.getPoint(); final double[] found = result.getPoint();