- * @exception OptimizationException if the decomposition cannot be performed
+ * @exception ConvergenceException if the decomposition cannot be performed
*/
- private void qrDecomposition() throws OptimizationException {
+ private void qrDecomposition() throws ConvergenceException {
// initializations
for (int k = 0; k < cols; ++k) {
@@ -821,7 +810,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
norm2 += aki * aki;
}
if (Double.isInfinite(norm2) || Double.isNaN(norm2)) {
- throw new OptimizationException(LocalizedFormats.UNABLE_TO_PERFORM_QR_DECOMPOSITION_ON_JACOBIAN,
+ throw new ConvergenceException(LocalizedFormats.UNABLE_TO_PERFORM_QR_DECOMPOSITION_ON_JACOBIAN,
rows, cols);
}
if (norm2 > ak2) {
@@ -858,11 +847,8 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
weightedResidualJacobian[j][permutation[k + dk]] -= gamma * weightedResidualJacobian[j][pk];
}
}
-
}
-
rank = solvedCols;
-
}
/**
@@ -883,5 +869,4 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
}
}
}
-
}
diff --git a/src/main/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizer.java b/src/main/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizer.java
index b1aa4f2c1..670077ad8 100644
--- a/src/main/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizer.java
+++ b/src/main/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizer.java
@@ -17,14 +17,14 @@
package org.apache.commons.math.optimization.general;
-import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.MathIllegalStateException;
+import org.apache.commons.math.exception.ConvergenceException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.analysis.solvers.BrentSolver;
import org.apache.commons.math.analysis.solvers.UnivariateRealSolver;
import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.optimization.GoalType;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.RealPointValuePair;
import org.apache.commons.math.util.FastMath;
@@ -54,11 +54,11 @@ public class NonLinearConjugateGradientOptimizer
/** Current point. */
private double[] point;
- /** Simple constructor with default settings.
- * The convergence check is set to a {@link
- * org.apache.commons.math.optimization.SimpleVectorialValueChecker}
- * and the maximal number of iterations is set to
- * {@link AbstractScalarDifferentiableOptimizer#DEFAULT_MAX_ITERATIONS}.
+ /**
+ * Simple constructor with default settings.
+ * The convergence check is set to a {@link
+ * org.apache.commons.math.optimization.SimpleVectorialValueChecker}.
+ *
* @param updateFormula formula to use for updating the β parameter,
* must be one of {@link ConjugateGradientFormula#FLETCHER_REEVES} or {@link
* ConjugateGradientFormula#POLAK_RIBIERE}
@@ -110,104 +110,104 @@ public class NonLinearConjugateGradientOptimizer
/** {@inheritDoc} */
@Override
protected RealPointValuePair doOptimize()
- throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
- try {
- // initialization
- if (preconditioner == null) {
- preconditioner = new IdentityPreconditioner();
+ throws FunctionEvaluationException {
+ // Initialization.
+ if (preconditioner == null) {
+ preconditioner = new IdentityPreconditioner();
+ }
+ if (solver == null) {
+ solver = new BrentSolver();
+ }
+ point = getStartPoint();
+ final GoalType goal = getGoalType();
+ final int n = point.length;
+ double[] r = computeObjectiveGradient(point);
+ if (goal == GoalType.MINIMIZE) {
+ for (int i = 0; i < n; ++i) {
+ r[i] = -r[i];
}
- if (solver == null) {
- solver = new BrentSolver();
+ }
+
+ // Initial search direction.
+ double[] steepestDescent = preconditioner.precondition(point, r);
+ double[] searchDirection = steepestDescent.clone();
+
+ double delta = 0;
+ for (int i = 0; i < n; ++i) {
+ delta += r[i] * searchDirection[i];
+ }
+
+ RealPointValuePair current = null;
+ int iter = 0;
+ while (true) {
+ ++iter;
+
+ final double objective = computeObjectiveValue(point);
+ RealPointValuePair previous = current;
+ current = new RealPointValuePair(point, objective);
+ if (previous != null) {
+ if (getConvergenceChecker().converged(iter, previous, current)) {
+ // We have found an optimum.
+ return current;
+ }
}
- point = getStartPoint();
- final GoalType goal = getGoalType();
- final int n = point.length;
- double[] r = computeObjectiveGradient(point);
+
+ double dTd = 0;
+ for (final double di : searchDirection) {
+ dTd += di * di;
+ }
+
+ // Find the optimal step in the search direction.
+ final UnivariateRealFunction lsf = new LineSearchFunction(searchDirection);
+ try {
+ final double step = solver.solve(lsf, 0, findUpperBound(lsf, 0, initialStep));
+
+ // Validate new point.
+ for (int i = 0; i < point.length; ++i) {
+ point[i] += step * searchDirection[i];
+ }
+ } catch (org.apache.commons.math.ConvergenceException e) {
+ throw new ConvergenceException(); // XXX ugly workaround.
+ }
+
+ r = computeObjectiveGradient(point);
if (goal == GoalType.MINIMIZE) {
for (int i = 0; i < n; ++i) {
r[i] = -r[i];
}
}
- // initial search direction
- double[] steepestDescent = preconditioner.precondition(point, r);
- double[] searchDirection = steepestDescent.clone();
-
- double delta = 0;
+ // Compute beta.
+ final double deltaOld = delta;
+ final double[] newSteepestDescent = preconditioner.precondition(point, r);
+ delta = 0;
for (int i = 0; i < n; ++i) {
- delta += r[i] * searchDirection[i];
+ delta += r[i] * newSteepestDescent[i];
}
- RealPointValuePair current = null;
- while (true) {
-
- final double objective = computeObjectiveValue(point);
- RealPointValuePair previous = current;
- current = new RealPointValuePair(point, objective);
- if (previous != null) {
- if (getConvergenceChecker().converged(getIterations(), previous, current)) {
- // we have found an optimum
- return current;
- }
+ final double beta;
+ if (updateFormula == ConjugateGradientFormula.FLETCHER_REEVES) {
+ beta = delta / deltaOld;
+ } else {
+ double deltaMid = 0;
+ for (int i = 0; i < r.length; ++i) {
+ deltaMid += r[i] * steepestDescent[i];
}
+ beta = (delta - deltaMid) / deltaOld;
+ }
+ steepestDescent = newSteepestDescent;
- incrementIterationsCounter();
-
- double dTd = 0;
- for (final double di : searchDirection) {
- dTd += di * di;
- }
-
- // find the optimal step in the search direction
- final UnivariateRealFunction lsf = new LineSearchFunction(searchDirection);
- final double step = solver.solve(lsf, 0, findUpperBound(lsf, 0, initialStep));
-
- // validate new point
- for (int i = 0; i < point.length; ++i) {
- point[i] += step * searchDirection[i];
- }
- r = computeObjectiveGradient(point);
- if (goal == GoalType.MINIMIZE) {
- for (int i = 0; i < n; ++i) {
- r[i] = -r[i];
- }
- }
-
- // compute beta
- final double deltaOld = delta;
- final double[] newSteepestDescent = preconditioner.precondition(point, r);
- delta = 0;
+ // Compute conjugate search direction.
+ if (iter % n == 0 ||
+ beta < 0) {
+ // Break conjugation: reset search direction.
+ searchDirection = steepestDescent.clone();
+ } else {
+ // Compute new conjugate search direction.
for (int i = 0; i < n; ++i) {
- delta += r[i] * newSteepestDescent[i];
+ searchDirection[i] = steepestDescent[i] + beta * searchDirection[i];
}
-
- final double beta;
- if (updateFormula == ConjugateGradientFormula.FLETCHER_REEVES) {
- beta = delta / deltaOld;
- } else {
- double deltaMid = 0;
- for (int i = 0; i < r.length; ++i) {
- deltaMid += r[i] * steepestDescent[i];
- }
- beta = (delta - deltaMid) / deltaOld;
- }
- steepestDescent = newSteepestDescent;
-
- // compute conjugate search direction
- if ((getIterations() % n == 0) || (beta < 0)) {
- // break conjugation: reset search direction
- searchDirection = steepestDescent.clone();
- } else {
- // compute new conjugate search direction
- for (int i = 0; i < n; ++i) {
- searchDirection[i] = steepestDescent[i] + beta * searchDirection[i];
- }
- }
-
}
-
- } catch (ConvergenceException ce) {
- throw new OptimizationException(ce);
}
}
@@ -218,11 +218,12 @@ public class NonLinearConjugateGradientOptimizer
* @param h initial step to try
* @return b such that f(a) and f(b) have opposite signs
* @exception FunctionEvaluationException if the function cannot be computed
- * @exception OptimizationException if no bracket can be found
+ * @exception MathIllegalStateException if no bracket can be found
+ * @deprecated in 2.2 (must be replaced with "BracketFinder").
*/
private double findUpperBound(final UnivariateRealFunction f,
final double a, final double h)
- throws FunctionEvaluationException, OptimizationException {
+ throws FunctionEvaluationException {
final double yA = f.value(a);
double yB = yA;
for (double step = h; step < Double.MAX_VALUE; step *= FastMath.max(2, yA / yB)) {
@@ -232,7 +233,7 @@ public class NonLinearConjugateGradientOptimizer
return b;
}
}
- throw new OptimizationException(LocalizedFormats.UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH);
+ throw new MathIllegalStateException(LocalizedFormats.UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH);
}
/** Default identity preconditioner. */
diff --git a/src/main/java/org/apache/commons/math/optimization/general/PowellOptimizer.java b/src/main/java/org/apache/commons/math/optimization/general/PowellOptimizer.java
index e35b238fd..45eef67c4 100644
--- a/src/main/java/org/apache/commons/math/optimization/general/PowellOptimizer.java
+++ b/src/main/java/org/apache/commons/math/optimization/general/PowellOptimizer.java
@@ -20,77 +20,69 @@ package org.apache.commons.math.optimization.general;
import java.util.Arrays;
import org.apache.commons.math.FunctionEvaluationException;
-import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.optimization.GoalType;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.RealPointValuePair;
+import org.apache.commons.math.optimization.ConvergenceChecker;
import org.apache.commons.math.optimization.univariate.AbstractUnivariateRealOptimizer;
import org.apache.commons.math.optimization.univariate.BracketFinder;
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
+import org.apache.commons.math.optimization.univariate.UnivariateRealPointValuePair;
/**
* Powell algorithm.
* This code is translated and adapted from the Python version of this
* algorithm (as implemented in module {@code optimize.py} v0.5 of
* SciPy).
+ *
+ * The user is responsible for calling {@link
+ * #setConvergenceChecker(ConvergenceChecker) ConvergenceChecker}
+ * prior to using the optimizer.
*
* @version $Revision$ $Date$
* @since 2.2
*/
public class PowellOptimizer
extends AbstractScalarOptimizer {
- /**
- * Default relative tolerance for line search ({@value}).
- */
- 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.
*/
- private final LineSearch line;
+ private LineSearch line = new LineSearch();
/**
- * Constructor with default line search tolerances (see the
- * {@link #PowellOptimizer(double,double) other constructor}).
- */
- public PowellOptimizer() {
- this(DEFAULT_LS_RELATIVE_TOLERANCE,
- DEFAULT_LS_ABSOLUTE_TOLERANCE);
- }
-
- /**
- * Constructor with default absolute line search tolerances (see
- * the {@link #PowellOptimizer(double,double) other constructor}).
+ * Set the convergence checker.
+ * It also indirectly sets the line search tolerances to the square-root
+ * of the correponding tolerances in the checker.
*
- * @param lsRelativeTolerance Relative error tolerance for
- * the line search algorithm ({@link BrentOptimizer}).
+ * @param checker Convergence checker.
*/
- public PowellOptimizer(double lsRelativeTolerance) {
- this(lsRelativeTolerance,
- DEFAULT_LS_ABSOLUTE_TOLERANCE);
+ public void setConvergenceChecker(ConvergenceChecker checker) {
+ super.setConvergenceChecker(checker);
+
+ // Line search tolerances can be much lower than the tolerances
+ // required for the optimizer itself.
+ final double minTol = 1e-4;
+ final double rel = Math.min(Math.sqrt(checker.getRelativeThreshold()), minTol);
+ final double abs = Math.min(Math.sqrt(checker.getAbsoluteThreshold()), minTol);
+ line.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(rel, abs));
}
- /**
- * @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} */
+ @Override
+ public void setMaxEvaluations(int maxEvaluations) {
+ super.setMaxEvaluations(maxEvaluations);
+
+ // We must allow at least as many iterations to the underlying line
+ // search optimizer. Because the line search inner class will call
+ // "computeObjectiveValue" in this class, we ensure that this class
+ // will be the first to eventually throw "TooManyEvaluationsException".
+ line.setMaxEvaluations(maxEvaluations);
}
/** {@inheritDoc} */
@Override
protected RealPointValuePair doOptimize()
- throws FunctionEvaluationException,
- OptimizationException {
+ throws FunctionEvaluationException {
final GoalType goal = getGoalType();
final double[] guess = getStartPoint();
final int n = guess.length;
@@ -103,8 +95,9 @@ public class PowellOptimizer
double[] x = guess;
double fVal = computeObjectiveValue(x);
double[] x1 = x.clone();
+ int iter = 0;
while (true) {
- incrementIterationsCounter();
+ ++iter;
double fX = fVal;
double fX2 = 0;
@@ -117,9 +110,9 @@ public class PowellOptimizer
fX2 = fVal;
- line.search(x, d);
- fVal = line.getValueAtOptimum();
- alphaMin = line.getOptimum();
+ final UnivariateRealPointValuePair optimum = line.search(x, d);
+ fVal = optimum.getValue();
+ alphaMin = optimum.getPoint();
final double[][] result = newPointAndDirection(x, d, alphaMin);
x = result[0];
@@ -131,7 +124,7 @@ public class PowellOptimizer
final RealPointValuePair previous = new RealPointValuePair(x1, fX);
final RealPointValuePair current = new RealPointValuePair(x, fVal);
- if (getConvergenceChecker().converged(getIterations(), previous, current)) {
+ if (getConvergenceChecker().converged(iter, previous, current)) {
if (goal == GoalType.MINIMIZE) {
return (fVal < fX) ? current : previous;
} else {
@@ -157,9 +150,9 @@ public class PowellOptimizer
t -= delta * temp * temp;
if (t < 0.0) {
- line.search(x, d);
- fVal = line.getValueAtOptimum();
- alphaMin = line.getOptimum();
+ final UnivariateRealPointValuePair optimum = line.search(x, d);
+ fVal = optimum.getValue();
+ alphaMin = optimum.getPoint();
final double[][] result = newPointAndDirection(x, d, alphaMin);
x = result[0];
@@ -200,11 +193,7 @@ public class PowellOptimizer
* Class for finding the minimum of the objective function along a given
* direction.
*/
- private class LineSearch {
- /**
- * Optimizer.
- */
- private final AbstractUnivariateRealOptimizer optim = new BrentOptimizer();
+ private class LineSearch extends BrentOptimizer {
/**
* Automatic bracketing.
*/
@@ -212,78 +201,41 @@ public class PowellOptimizer
/**
* Value of the optimum.
*/
- private double optimum = Double.NaN;
- /**
- * Value of the objective function at the optimum.
- */
- private double valueAtOptimum = Double.NaN;
-
- /**
- * @param relativeTolerance Relative tolerance.
- * @param absoluteTolerance Absolute tolerance.
- */
- public LineSearch(double relativeTolerance,
- double absoluteTolerance) {
- optim.setRelativeAccuracy(relativeTolerance);
- optim.setAbsoluteAccuracy(absoluteTolerance);
- }
+ private UnivariateRealPointValuePair optimum;
/**
* Find the minimum of the function {@code f(p + alpha * d)}.
*
* @param p Starting point.
* @param d Search direction.
- * @throws OptimizationException if function cannot be evaluated at some test point
- * or algorithm fails to converge
- */
- public void search(final double[] p,
- final double[] d)
- throws OptimizationException {
-
- // Reset.
- optimum = Double.NaN;
- valueAtOptimum = Double.NaN;
-
- try {
- final int n = p.length;
- final UnivariateRealFunction f = new UnivariateRealFunction() {
- public double value(double alpha)
- throws FunctionEvaluationException {
-
- final double[] x = new double[n];
- for (int i = 0; i < n; i++) {
- x[i] = p[i] + alpha * d[i];
- }
- final double obj = computeObjectiveValue(x);
- return obj;
- }
- };
-
- final GoalType goal = getGoalType();
- bracket.search(f, goal, 0, 1);
- optimum = optim.optimize(f, goal,
- bracket.getLo(),
- bracket.getHi(),
- bracket.getMid());
- valueAtOptimum = optim.getFunctionValue();
- } catch (FunctionEvaluationException e) {
- throw new OptimizationException(e);
- } catch (MaxIterationsExceededException e) {
- throw new OptimizationException(e);
- }
- }
-
- /**
* @return the optimum.
+ * @throws FunctionEvaluationException if the function evaluation
+ * fails.
+ * @throws TooManyEvaluationsException if the number of evaluations is
+ * exceeded.
*/
- public double getOptimum() {
- return optimum;
- }
- /**
- * @return the value of the function at the optimum.
- */
- public double getValueAtOptimum() {
- return valueAtOptimum;
+ public UnivariateRealPointValuePair search(final double[] p,
+ final double[] d)
+ throws FunctionEvaluationException {
+
+ final int n = p.length;
+ final UnivariateRealFunction f = new UnivariateRealFunction() {
+ public double value(double alpha)
+ throws FunctionEvaluationException {
+
+ final double[] x = new double[n];
+ for (int i = 0; i < n; i++) {
+ x[i] = p[i] + alpha * d[i];
+ }
+ final double obj = PowellOptimizer.this.computeObjectiveValue(x);
+ return obj;
+ }
+ };
+
+ final GoalType goal = PowellOptimizer.this.getGoalType();
+ bracket.search(f, goal, 0, 1);
+ return optimize(f, goal, bracket.getLo(), bracket.getHi(),
+ bracket.getMid());
}
}
}
diff --git a/src/main/java/org/apache/commons/math/optimization/package.html b/src/main/java/org/apache/commons/math/optimization/package.html
index 27b32b3f3..da0ae6fab 100644
--- a/src/main/java/org/apache/commons/math/optimization/package.html
+++ b/src/main/java/org/apache/commons/math/optimization/package.html
@@ -33,7 +33,7 @@ by changing its input variables set until an optimal set is found. There are onl
interfaces defining the common behavior of optimizers, one for each supported type of objective
function:
- - {@link org.apache.commons.math.optimization.UnivariateRealOptimizer
+
- {@link org.apache.commons.math.optimization.univariate.UnivariateRealOptimizer
UnivariateRealOptimizer} for {@link org.apache.commons.math.analysis.UnivariateRealFunction
univariate real functions}
- {@link org.apache.commons.math.optimization.MultivariateRealOptimizer
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/AbstractUnivariateRealOptimizer.java b/src/main/java/org/apache/commons/math/optimization/univariate/AbstractUnivariateRealOptimizer.java
index 4ed395ff5..913397c18 100644
--- a/src/main/java/org/apache/commons/math/optimization/univariate/AbstractUnivariateRealOptimizer.java
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/AbstractUnivariateRealOptimizer.java
@@ -17,14 +17,13 @@
package org.apache.commons.math.optimization.univariate;
-import org.apache.commons.math.ConvergingAlgorithmImpl;
import org.apache.commons.math.FunctionEvaluationException;
-import org.apache.commons.math.MaxEvaluationsExceededException;
-import org.apache.commons.math.MaxIterationsExceededException;
+import org.apache.commons.math.util.Incrementor;
+import org.apache.commons.math.exception.MaxCountExceededException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
-import org.apache.commons.math.exception.NoDataException;
import org.apache.commons.math.optimization.GoalType;
-import org.apache.commons.math.optimization.UnivariateRealOptimizer;
+import org.apache.commons.math.optimization.ConvergenceChecker;
/**
* Provide a default implementation for several functions useful to generic
@@ -34,19 +33,13 @@ import org.apache.commons.math.optimization.UnivariateRealOptimizer;
* @since 2.0
*/
public abstract class AbstractUnivariateRealOptimizer
- extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer {
- /** Indicates where a root has been computed. */
- private boolean resultComputed;
- /** The last computed root. */
- private double result;
- /** Value of the function at the last computed result. */
- private double functionValue;
- /** Maximal number of evaluations allowed. */
- private int maxEvaluations;
- /** Number of evaluations already performed. */
- private int evaluations;
+ implements UnivariateRealOptimizer {
+ /** Convergence checker. */
+ private ConvergenceChecker checker;
+ /** Evaluations counter. */
+ private final Incrementor evaluations = new Incrementor();
/** Optimization type */
- private GoalType optimizationGoal;
+ private GoalType goal;
/** Lower end of search interval. */
private double searchMin;
/** Higher end of search interval. */
@@ -56,115 +49,35 @@ public abstract class AbstractUnivariateRealOptimizer
/** Function to optimize. */
private UnivariateRealFunction function;
- /**
- * Construct a solver with given iteration count and accuracy.
- * FunctionEvaluationExceptionFunctionEvaluationException
- * @param defaultAbsoluteAccuracy maximum absolute error
- * @param defaultMaximalIterationCount maximum number of iterations
- * @throws IllegalArgumentException if f is null or the
- * defaultAbsoluteAccuracy is not valid
- * @deprecated in 2.2. Please use the "setter" methods to assign meaningful
- * values to the maximum numbers of iterations and evaluations, and to the
- * absolute and relative accuracy thresholds.
- */
- protected AbstractUnivariateRealOptimizer(final int defaultMaximalIterationCount,
- final double defaultAbsoluteAccuracy) {
- super(defaultMaximalIterationCount, defaultAbsoluteAccuracy);
- resultComputed = false;
- setMaxEvaluations(Integer.MAX_VALUE);
- }
-
- /**
- * Default constructor.
- * To be removed once the single non-default one has been removed.
- */
- protected AbstractUnivariateRealOptimizer() {}
-
- /**
- * Check whether a result has been computed.
- * @throws NoDataException if no result has been computed
- * @deprecated in 2.2 (no alternative).
- */
- protected void checkResultComputed() {
- if (!resultComputed) {
- throw new NoDataException();
- }
- }
-
- /** {@inheritDoc} */
- public double getResult() {
- if (!resultComputed) {
- throw new NoDataException();
- }
- return result;
- }
-
- /** {@inheritDoc} */
- public double getFunctionValue() {
- if (functionValue == Double.NaN) {
- final double opt = getResult();
- try {
- functionValue = function.value(opt);
- } catch (FunctionEvaluationException e) {
- throw new RuntimeException(e);
- }
- }
- return functionValue;
- }
-
- /**
- * Convenience function for implementations.
- *
- * @param x the result to set
- * @param fx the result to set
- * @param iterationCount the iteration count to set
- * @deprecated in 2.2 (no alternative).
- */
- protected final void setResult(final double x, final double fx,
- final int iterationCount) {
- this.result = x;
- this.functionValue = fx;
- this.iterationCount = iterationCount;
- this.resultComputed = true;
- }
-
- /**
- * Convenience function for implementations.
- * @deprecated in 2.2 (no alternative).
- */
- protected final void clearResult() {
- this.resultComputed = false;
- }
-
/** {@inheritDoc} */
public void setMaxEvaluations(int maxEvaluations) {
- this.maxEvaluations = maxEvaluations;
+ evaluations.setMaximalCount(maxEvaluations);
}
/** {@inheritDoc} */
public int getMaxEvaluations() {
- return maxEvaluations;
+ return evaluations.getMaximalCount();
}
/** {@inheritDoc} */
public int getEvaluations() {
- return evaluations;
+ return evaluations.getCount();
}
/**
* @return the optimization type.
*/
public GoalType getGoalType() {
- return optimizationGoal;
+ return goal;
}
/**
- * @return the lower of the search interval.
+ * @return the lower end of the search interval.
*/
public double getMin() {
return searchMin;
}
/**
- * @return the higher of the search interval.
+ * @return the higher end of the search interval.
*/
public double getMax() {
return searchMax;
@@ -176,93 +89,76 @@ public abstract class AbstractUnivariateRealOptimizer
return searchStart;
}
- /**
- * Compute the objective function value.
- * @param f objective function
- * @param point point at which the objective function must be evaluated
- * @return objective function value at specified point
- * @exception FunctionEvaluationException if the function cannot be evaluated
- * or the maximal number of iterations is exceeded
- * @deprecated in 2.2. Use this {@link #computeObjectiveValue(double)
- * replacement} instead.
- */
- protected double computeObjectiveValue(final UnivariateRealFunction f,
- final double point)
- throws FunctionEvaluationException {
- if (++evaluations > maxEvaluations) {
- throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
- point);
- }
- return f.value(point);
- }
-
/**
* Compute the objective function value.
*
* @param point Point at which the objective function must be evaluated.
* @return the objective function value at specified point.
- * @exception FunctionEvaluationException if the function cannot be evaluated
- * or the maximal number of iterations is exceeded.
+ * @throws FunctionEvaluationException if the function cannot be
+ * evaluated.
+ * @throws TooManyEvaluationsException if the maximal number of evaluations
+ * is exceeded.
*/
protected double computeObjectiveValue(double point)
throws FunctionEvaluationException {
- if (++evaluations > maxEvaluations) {
- resultComputed = false;
- throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
- point);
+ try {
+ evaluations.incrementCount();
+ } catch (MaxCountExceededException e) {
+ throw new TooManyEvaluationsException(e.getMax());
}
return function.value(point);
}
/** {@inheritDoc} */
- public double optimize(UnivariateRealFunction f, GoalType goal,
- double min, double max, double startValue)
- throws MaxIterationsExceededException, FunctionEvaluationException {
- // Initialize.
- this.searchMin = min;
- this.searchMax = max;
- this.searchStart = startValue;
- this.optimizationGoal = goal;
- this.function = f;
-
+ public UnivariateRealPointValuePair optimize(UnivariateRealFunction f,
+ GoalType goalType,
+ double min, double max,
+ double startValue)
+ throws FunctionEvaluationException {
// Reset.
- functionValue = Double.NaN;
- evaluations = 0;
- resetIterationsCounter();
+ searchMin = min;
+ searchMax = max;
+ searchStart = startValue;
+ goal = goalType;
+ function = f;
+ evaluations.resetCount();
// Perform computation.
- result = doOptimize();
- resultComputed = true;
-
- return result;
- }
-
- /**
- * Set the value at the optimum.
- *
- * @param functionValue Value of the objective function at the optimum.
- */
- protected void setFunctionValue(double functionValue) {
- this.functionValue = functionValue;
+ return doOptimize();
}
/** {@inheritDoc} */
- public double optimize(UnivariateRealFunction f, GoalType goal,
- double min, double max)
- throws MaxIterationsExceededException, FunctionEvaluationException {
+ public UnivariateRealPointValuePair optimize(UnivariateRealFunction f,
+ GoalType goal,
+ double min, double max)
+ throws FunctionEvaluationException {
return optimize(f, goal, min, max, min + 0.5 * (max - min));
}
+ /**
+ * {@inheritDoc}
+ */
+ public void setConvergenceChecker(ConvergenceChecker checker) {
+ this.checker = checker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConvergenceChecker getConvergenceChecker() {
+ return checker;
+ }
+
/**
* Method for implementing actual optimization algorithms in derived
* classes.
*
- * @return the optimum.
- * @throws MaxIterationsExceededException if the maximum iteration count
+ * @return the optimum and its corresponding function value.
+ * @throws TooManyEvaluationsException if the maximal number of evaluations
* is exceeded.
* @throws FunctionEvaluationException if an error occurs evaluating
* the function.
*/
- protected abstract double doOptimize()
- throws MaxIterationsExceededException, FunctionEvaluationException;
+ protected abstract UnivariateRealPointValuePair doOptimize()
+ throws FunctionEvaluationException;
}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/BaseUnivariateRealOptimizer.java b/src/main/java/org/apache/commons/math/optimization/univariate/BaseUnivariateRealOptimizer.java
new file mode 100644
index 000000000..46b64aa53
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/BaseUnivariateRealOptimizer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.optimization.univariate;
+
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.optimization.BaseOptimizer;
+import org.apache.commons.math.optimization.GoalType;
+
+/**
+ * This interface is mainly intended to enforce the internal coherence of
+ * Commons-Math. Users of the API are advised to base their code on
+ * the following interfaces:
+ *
+ * - {@link org.apache.commons.math.optimization.univariate.UnivariateRealOptimizer}
+ *
+ *
+ * @param Type of the objective function to be optimized.
+ *
+ * @version $Revision$ $Date$
+ * @since 3.0
+ */
+public interface BaseUnivariateRealOptimizer
+ extends BaseOptimizer {
+ /**
+ * Find an optimum in the given interval.
+ *
+ * An optimizer may require that the interval brackets a single optimum.
+ *
+ * @param f Function to optimize.
+ * @param goalType Type of optimization goal: either
+ * {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
+ * @param min Lower bound for the interval.
+ * @param max Upper bound for the interval.
+ * @return a (point, value) pair where the function is optimum.
+ * @throws {@link org.apache.commons.math.exception.TooManyEvaluationsException}
+ * if the maximum evaluation count is exceeded.
+ * @throws {@link org.apache.commons.math.exception.ConvergenceException}
+ * if the optimizer detects a convergence problem.
+ * @throws FunctionEvaluationException if an error occurs evaluating the
+ * function.
+ * @throws IllegalArgumentException if {@code min > max} or the endpoints
+ * do not satisfy the requirements specified by the optimizer.
+ */
+ UnivariateRealPointValuePair optimize(FUNC f, GoalType goalType,
+ double min, double max)
+ throws FunctionEvaluationException;
+
+ /**
+ * Find an optimum in the given interval, start at startValue.
+ * An optimizer may require that the interval brackets a single optimum.
+ *
+ * @param f Function to optimize.
+ * @param goalType Type of optimization goal: either
+ * {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
+ * @param min Lower bound for the interval.
+ * @param max Upper bound for the interval.
+ * @param startValue Start value to use.
+ * @return a (point, value) pair where the function is optimum.
+ * @throws {@link org.apache.commons.math.exception.TooManyEvaluationsException}
+ * if the maximum evaluation count is exceeded.
+ * @throws {@link org.apache.commons.math.exception.ConvergenceException}
+ * if the optimizer detects a convergence problem.
+ * @throws FunctionEvaluationException if an error occurs evaluating the
+ * function.
+ * @throws IllegalArgumentException if {@code min > max} or the endpoints
+ * do not satisfy the requirements specified by the optimizer.
+ */
+ UnivariateRealPointValuePair optimize(FUNC f, GoalType goalType,
+ double min, double max,
+ double startValue)
+ throws FunctionEvaluationException;
+}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/BracketFinder.java b/src/main/java/org/apache/commons/math/optimization/univariate/BracketFinder.java
index 56a6f28cf..bd60087fe 100644
--- a/src/main/java/org/apache/commons/math/optimization/univariate/BracketFinder.java
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/BracketFinder.java
@@ -16,9 +16,11 @@
*/
package org.apache.commons.math.optimization.univariate;
+import org.apache.commons.math.util.Incrementor;
import org.apache.commons.math.exception.NotStrictlyPositiveException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
+import org.apache.commons.math.exception.MaxCountExceededException;
import org.apache.commons.math.FunctionEvaluationException;
-import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.optimization.GoalType;
@@ -26,6 +28,7 @@ import org.apache.commons.math.optimization.GoalType;
* Provide an interval that brackets a local optimum of a function.
* This code is based on a Python implementation (from SciPy,
* module {@code optimize.py} v0.5).
+ *
* @version $Revision$ $Date$
* @since 2.2
*/
@@ -41,17 +44,9 @@ public class BracketFinder {
*/
private final double growLimit;
/**
- * Maximum number of iterations.
+ * Counter for function evaluations.
*/
- private final int maxIterations;
- /**
- * Number of iterations.
- */
- private int iterations;
- /**
- * Number of function evaluations.
- */
- private int evaluations;
+ private final Incrementor evaluations = new Incrementor();
/**
* Lower bound of the bracket.
*/
@@ -89,20 +84,20 @@ public class BracketFinder {
* Create a bracketing interval finder.
*
* @param growLimit Expanding factor.
- * @param maxIterations Maximum number of iterations allowed for finding
+ * @param maxEvaluations Maximum number of evaluations allowed for finding
* a bracketing interval.
*/
public BracketFinder(double growLimit,
- int maxIterations) {
+ int maxEvaluations) {
if (growLimit <= 0) {
throw new NotStrictlyPositiveException(growLimit);
}
- if (maxIterations <= 0) {
- throw new NotStrictlyPositiveException(maxIterations);
+ if (maxEvaluations <= 0) {
+ throw new NotStrictlyPositiveException(maxEvaluations);
}
this.growLimit = growLimit;
- this.maxIterations = maxIterations;
+ evaluations.setMaximalCount(maxEvaluations);
}
/**
@@ -112,7 +107,7 @@ public class BracketFinder {
* @param goal {@link GoalType Goal type}.
* @param xA Initial point.
* @param xB Initial point.
- * @throws MaxIterationsExceededException if the maximum iteration count
+ * @throws TooManyEvaluationsException if the maximum number of evaluations
* is exceeded.
* @throws FunctionEvaluationException if an error occurs evaluating
* the function.
@@ -121,9 +116,8 @@ public class BracketFinder {
GoalType goal,
double xA,
double xB)
- throws MaxIterationsExceededException,
- FunctionEvaluationException {
- reset();
+ throws FunctionEvaluationException {
+ evaluations.resetCount();
final boolean isMinim = goal == GoalType.MINIMIZE;
double fA = eval(func, xA);
@@ -131,6 +125,7 @@ public class BracketFinder {
if (isMinim ?
fA < fB :
fA > fB) {
+
double tmp = xA;
xA = xB;
xB = tmp;
@@ -144,10 +139,6 @@ public class BracketFinder {
double fC = eval(func, xC);
while (isMinim ? fC < fB : fC > fB) {
- if (++iterations > maxIterations) {
- throw new MaxIterationsExceededException(maxIterations);
- }
-
double tmp1 = (xB - xA) * (fB - fC);
double tmp2 = (xB - xC) * (fB - fA);
@@ -187,7 +178,7 @@ public class BracketFinder {
fW > fC) {
xB = xC;
xC = w;
- w = xC + GOLD * (xC -xB);
+ w = xC + GOLD * (xC - xB);
fB = fC;
fC =fW;
fW = eval(func, w);
@@ -198,37 +189,48 @@ public class BracketFinder {
}
xA = xB;
- xB = xC;
- xC = w;
fA = fB;
+ xB = xC;
fB = fC;
+ xC = w;
fC = fW;
}
lo = xA;
- mid = xB;
- hi = xC;
fLo = fA;
+ mid = xB;
fMid = fB;
+ hi = xC;
fHi = fC;
+
+ if (lo > hi) {
+ double tmp = lo;
+ lo = hi;
+ hi = tmp;
+
+ tmp = fLo;
+ fLo = fHi;
+ fHi = tmp;
+ }
}
/**
- * @return the number of iterations.
+ * @return the number of evalutations.
*/
- public int getIterations() {
- return iterations;
+ public int getMaxEvaluations() {
+ return evaluations.getMaximalCount();
}
+
/**
* @return the number of evalutations.
*/
public int getEvaluations() {
- return evaluations;
+ return evaluations.getCount();
}
/**
* @return the lower bound of the bracket.
- * @see #getFLow()
+ * @see #getFLo()
*/
public double getLo() {
return lo;
@@ -238,7 +240,7 @@ public class BracketFinder {
* Get function value at {@link #getLo()}.
* @return function value at {@link #getLo()}
*/
- public double getFLow() {
+ public double getFLo() {
return fLo;
}
@@ -278,21 +280,18 @@ public class BracketFinder {
* @param f Function.
* @param x Argument.
* @return {@code f(x)}
- * @throws FunctionEvaluationException if function cannot be evaluated at x
+ * @throws FunctionEvaluationException if function cannot be evaluated.
+ * @throws TooManyEvaluationsException if the maximal number of evaluations is
+ * exceeded.
*/
private double eval(UnivariateRealFunction f,
double x)
throws FunctionEvaluationException {
-
- ++evaluations;
+ try {
+ evaluations.incrementCount();
+ } catch (MaxCountExceededException e) {
+ throw new TooManyEvaluationsException(e.getMax());
+ }
return f.value(x);
}
-
- /**
- * Reset internal state.
- */
- private void reset() {
- iterations = 0;
- evaluations = 0;
- }
}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/BrentOptimizer.java b/src/main/java/org/apache/commons/math/optimization/univariate/BrentOptimizer.java
index 67f58b49e..c10581f23 100644
--- a/src/main/java/org/apache/commons/math/optimization/univariate/BrentOptimizer.java
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/BrentOptimizer.java
@@ -17,16 +17,28 @@
package org.apache.commons.math.optimization.univariate;
import org.apache.commons.math.FunctionEvaluationException;
-import org.apache.commons.math.MaxIterationsExceededException;
-import org.apache.commons.math.exception.NotStrictlyPositiveException;
-import org.apache.commons.math.optimization.GoalType;
+import org.apache.commons.math.util.MathUtils;
import org.apache.commons.math.util.FastMath;
+import org.apache.commons.math.exception.DimensionMismatchException;
+import org.apache.commons.math.exception.NumberIsTooSmallException;
+import org.apache.commons.math.exception.NotStrictlyPositiveException;
+import org.apache.commons.math.exception.MathUnsupportedOperationException;
+import org.apache.commons.math.optimization.ConvergenceChecker;
+import org.apache.commons.math.optimization.AbstractConvergenceChecker;
+import org.apache.commons.math.optimization.GoalType;
/**
* Implements Richard Brent's algorithm (from his book "Algorithms for
* Minimization without Derivatives", p. 79) for finding minima of real
* univariate functions. This implementation is an adaptation partly
* based on the Python code from SciPy (module "optimize.py" v0.5).
+ * If the function is defined on some interval {@code (lo, hi)}, then
+ * this method finds an approximation {@code x} to the point at which
+ * the function attains its minimum.
+ *
+ * The user is responsible for calling {@link
+ * #setConvergenceChecker(ConvergenceChecker) ConvergenceChecker}
+ * prior to using the optimizer.
*
* @version $Revision$ $Date$
* @since 2.0
@@ -38,57 +50,105 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
private static final double GOLDEN_SECTION = 0.5 * (3 - FastMath.sqrt(5));
/**
- * Construct a solver.
+ * Convergence checker that implements the original stopping criterion
+ * of Brent's algorithm.
+ * {@code abs} and {@code rel} define a tolerance
+ * {@code tol = rel |x| + abs}. {@code rel} should be no smaller than
+ * 2 macheps and preferably not much less than sqrt(macheps),
+ * where macheps is the relative machine precision. {@code abs} must
+ * be positive.
+ *
+ * @since 3.0
*/
- public BrentOptimizer() {
- setMaxEvaluations(1000);
- setMaximalIterationCount(100);
- setAbsoluteAccuracy(1e-11);
- setRelativeAccuracy(1e-9);
- }
+ public static class BrentConvergenceChecker
+ extends AbstractConvergenceChecker {
+ /**
+ * Minimum relative tolerance.
+ */
+ private static final double MIN_RELATIVE_TOLERANCE = 2 * FastMath.ulp(1d);
- /** {@inheritDoc} */
- protected double doOptimize()
- throws MaxIterationsExceededException, FunctionEvaluationException {
- return localMin(getGoalType() == GoalType.MINIMIZE,
- getMin(), getStartValue(), getMax(),
- getRelativeAccuracy(), getAbsoluteAccuracy());
+ /**
+ * Build an instance with specified thresholds.
+ *
+ * @param rel Relative tolerance threshold
+ * @param abs Absolute tolerance threshold
+ */
+ public BrentConvergenceChecker(final double rel,
+ final double abs) {
+ super(rel, abs);
+
+ if (rel < MIN_RELATIVE_TOLERANCE) {
+ throw new NumberIsTooSmallException(rel, MIN_RELATIVE_TOLERANCE, true);
+ }
+ if (abs <= 0) {
+ throw new NotStrictlyPositiveException(abs);
+ }
+ }
+
+ /**
+ * Convergence criterion.
+ *
+ * @param iteration Current iteration.
+ * @param points Points used for checking the stopping criterion. The list
+ * must contain 3 points (in the following order):
+ *
+ * - the lower end of the current interval
+ * - the current best point
+ * - the higher end of the current interval
+ *
+ * @return {@code true} if the stopping criterion is satisfied.
+ * @throws DimensionMismatchException if the length of the {@code points}
+ * list is not equal to 3.
+ */
+ public boolean converged(final int iteration,
+ final UnivariateRealPointValuePair ... points) {
+ if (points.length != 3) {
+ throw new DimensionMismatchException(points.length, 3);
+ }
+
+ final double a = points[0].getPoint();
+ final double x = points[1].getPoint();
+ final double b = points[2].getPoint();
+
+ final double tol1 = getRelativeThreshold() * FastMath.abs(x) + getAbsoluteThreshold();
+ final double tol2 = 2 * tol1;
+
+ final double m = 0.5 * (a + b);
+ return FastMath.abs(x - m) <= tol2 - 0.5 * (b - a);
+ }
}
/**
- * Find the minimum of the function within the interval {@code (lo, hi)}.
+ * Set the convergence checker.
+ * Since this algorithm requires a specific checker, this method will throw
+ * an {@code UnsupportedOperationexception} if the argument type is not
+ * {@link BrentConvergenceChecker}.
*
- * If the function is defined on the interval {@code (lo, hi)}, then
- * this method finds an approximation {@code x} to the point at which
- * the function attains its minimum.
- * {@code t} and {@code eps} define a tolerance {@code tol = eps |x| + t}
- * and the function is never evaluated at two points closer together than
- * {@code tol}. {@code eps} should be no smaller than 2 macheps and
- * preferable not much less than sqrt(macheps), where
- * macheps is the relative machine precision. {@code t} should be
- * positive.
- * @param isMinim {@code true} when minimizing the function.
- * @param lo Lower bound of the interval.
- * @param mid Point inside the interval {@code [lo, hi]}.
- * @param hi Higher bound of the interval.
- * @param eps Relative accuracy.
- * @param t Absolute accuracy.
- * @return the optimum point.
- * @throws MaxIterationsExceededException if the maximum iteration count
- * is exceeded.
- * @throws FunctionEvaluationException if an error occurs evaluating
- * the function.
+ * @throws MathUnsupportedOperationexception if the checker is not an
+ * instance of {@link BrentConvergenceChecker}.
*/
- private double localMin(boolean isMinim,
- double lo, double mid, double hi,
- double eps, double t)
- throws MaxIterationsExceededException, FunctionEvaluationException {
- if (eps <= 0) {
- throw new NotStrictlyPositiveException(eps);
- }
- if (t <= 0) {
- throw new NotStrictlyPositiveException(t);
+ @Override
+ public void setConvergenceChecker(ConvergenceChecker checker) {
+ if (checker instanceof BrentConvergenceChecker) {
+ super.setConvergenceChecker(checker);
+ } else {
+ throw new MathUnsupportedOperationException();
}
+ }
+
+ /** {@inheritDoc} */
+ protected UnivariateRealPointValuePair doOptimize()
+ throws FunctionEvaluationException {
+ final boolean isMinim = (getGoalType() == GoalType.MINIMIZE);
+ final double lo = getMin();
+ final double mid = getStartValue();
+ final double hi = getMax();
+
+ final ConvergenceChecker checker
+ = getConvergenceChecker();
+ final double eps = checker.getRelativeThreshold();
+ final double t = checker.getAbsoluteThreshold();
+
double a;
double b;
if (lo < hi) {
@@ -111,13 +171,19 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
double fv = fx;
double fw = fx;
+ int iter = 0;
while (true) {
double m = 0.5 * (a + b);
final double tol1 = eps * FastMath.abs(x) + t;
final double tol2 = 2 * tol1;
// Check stopping criterion.
- if (FastMath.abs(x - m) > tol2 - 0.5 * (b - a)) {
+ // This test will work only if the "checker" is an instance of
+ // "BrentOptimizer.BrentConvergenceChecker".
+ if (!getConvergenceChecker().converged(iter,
+ new UnivariateRealPointValuePair(a, Double.NaN),
+ new UnivariateRealPointValuePair(x, Double.NaN),
+ new UnivariateRealPointValuePair(b, Double.NaN))) {
double p = 0;
double q = 0;
double r = 0;
@@ -217,11 +283,10 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
fv = fu;
}
}
- } else { // termination
- setFunctionValue(isMinim ? fx : -fx);
- return x;
+ } else { // Termination.
+ return new UnivariateRealPointValuePair(x, (isMinim ? fx : -fx));
}
- incrementIterationsCounter();
+ ++iter;
}
}
}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizer.java b/src/main/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizer.java
new file mode 100644
index 000000000..aa14ce6c1
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizer.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.optimization.univariate;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.exception.MathIllegalStateException;
+import org.apache.commons.math.exception.ConvergenceException;
+import org.apache.commons.math.exception.util.LocalizedFormats;
+import org.apache.commons.math.random.RandomGenerator;
+import org.apache.commons.math.optimization.GoalType;
+import org.apache.commons.math.optimization.ConvergenceChecker;
+import org.apache.commons.math.util.FastMath;
+
+/**
+ * Special implementation of the {@link UnivariateRealOptimizer} interface
+ * adding multi-start features to an existing optimizer.
+ *
+ * This class wraps a classical optimizer to use it several times in
+ * turn with different starting points in order to avoid being trapped
+ * into a local extremum when looking for a global one.
+ *
+ * @param Type of the objective function to be optimized.
+ *
+ * @version $Revision$ $Date$
+ * @since 3.0
+ */
+public class MultiStartUnivariateRealOptimizer
+ implements BaseUnivariateRealOptimizer {
+ /** Underlying classical optimizer. */
+ private final BaseUnivariateRealOptimizer optimizer;
+ /** Maximal number of evaluations allowed. */
+ private int maxEvaluations;
+ /** Number of evaluations already performed for all starts. */
+ private int totalEvaluations;
+ /** Number of starts to go. */
+ private int starts;
+ /** Random generator for multi-start. */
+ private RandomGenerator generator;
+ /** Found optima. */
+ private UnivariateRealPointValuePair[] optima;
+
+ /**
+ * Create a multi-start optimizer from a single-start optimizer.
+ *
+ * @param optimizer Single-start optimizer to wrap.
+ * @param starts Number of starts to perform (including the
+ * first one), multi-start is disabled if value is less than or
+ * equal to 1.
+ * @param generator Random generator to use for restarts.
+ */
+ public MultiStartUnivariateRealOptimizer(final BaseUnivariateRealOptimizer optimizer,
+ final int starts,
+ final RandomGenerator generator) {
+ this.optimizer = optimizer;
+ this.starts = starts;
+ this.generator = generator;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setConvergenceChecker(ConvergenceChecker checker) {
+ optimizer.setConvergenceChecker(checker);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConvergenceChecker getConvergenceChecker() {
+ return optimizer.getConvergenceChecker();
+ }
+
+ /** {@inheritDoc} */
+ public int getMaxEvaluations() {
+ return maxEvaluations;
+ }
+
+ /** {@inheritDoc} */
+ public int getEvaluations() {
+ return totalEvaluations;
+ }
+
+ /** {@inheritDoc} */
+ public void setMaxEvaluations(int maxEvaluations) {
+ this.maxEvaluations = maxEvaluations;
+ optimizer.setMaxEvaluations(maxEvaluations);
+ }
+
+ /**
+ * Get all the optima found during the last call to {@link
+ * #optimize(FUNC,GoalType,double,double) optimize}.
+ * The optimizer stores all the optima found during a set of
+ * restarts. The {@link #optimize(FUNC,GoalType,double,double) optimize}
+ * method returns the best point only. This method returns all the points
+ * found at the end of each starts, including the best one already
+ * returned by the {@link #optimize(FUNC,GoalType,double,double) optimize}
+ * method.
+ *
+ * The returned array as one element for each start as specified
+ * in the constructor. It is ordered with the results from the
+ * runs that did converge first, sorted from best to worst
+ * objective value (i.e in ascending order if minimizing and in
+ * descending order if maximizing), followed by {@code null} elements
+ * corresponding to the runs that did not converge. This means all
+ * elements will be {@code null} if the {@link
+ * #optimize(FUNC,GoalType,double,double) optimize} method did throw a
+ * {@link ConvergenceException}). This also means that if the first
+ * element is not {@code null}, it is the best point found across all
+ * starts.
+ *
+ * @return an array containing the optima.
+ * @throws MathIllegalStateException if {@link
+ * #optimize(FUNC,GoalType,double,double) optimize} has not been called.
+ */
+ public UnivariateRealPointValuePair[] getOptima() {
+ if (optima == null) {
+ throw new MathIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
+ }
+ return optima.clone();
+ }
+
+ /** {@inheritDoc} */
+ public UnivariateRealPointValuePair optimize(final FUNC f,
+ final GoalType goal,
+ final double min, final double max)
+ throws FunctionEvaluationException {
+
+ optima = new UnivariateRealPointValuePair[starts];
+ totalEvaluations = 0;
+
+ // Multi-start loop.
+ for (int i = 0; i < starts; ++i) {
+ try {
+ final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min);
+ final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min);
+ optima[i] = optimizer.optimize(f, goal,
+ FastMath.min(bound1, bound2),
+ FastMath.max(bound1, bound2));
+ } catch (FunctionEvaluationException fee) {
+ optima[i] = null;
+ } catch (ConvergenceException ce) {
+ optima[i] = null;
+ }
+
+ final int usedEvaluations = optimizer.getEvaluations();
+ optimizer.setMaxEvaluations(optimizer.getMaxEvaluations() - usedEvaluations);
+ totalEvaluations += usedEvaluations;
+ }
+
+ sortPairs(goal);
+
+ if (optima[0] == null) {
+ throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
+ starts);
+ }
+
+ // Return the point with the best objective function value.
+ return optima[0];
+ }
+
+ /** {@inheritDoc} */
+ public UnivariateRealPointValuePair optimize(final FUNC f, final GoalType goalType,
+ final double min, final double max,
+ final double startValue)
+ throws FunctionEvaluationException {
+ // XXX Main code should be here, using "startValue" for the first start.
+ // XXX This method should set "startValue" to min + 0.5 * (max - min)
+ return optimize(f, goalType, min, max);
+ }
+
+ /**
+ * Sort the optima from best to worst, followed by {@code null} elements.
+ *
+ * @param goal Goal type.
+ */
+ private void sortPairs(final GoalType goal) {
+ Arrays.sort(optima, new Comparator() {
+ public int compare(final UnivariateRealPointValuePair o1,
+ final UnivariateRealPointValuePair o2) {
+ if (o1 == null) {
+ return (o2 == null) ? 0 : 1;
+ } else if (o2 == null) {
+ return -1;
+ }
+ final double v1 = o1.getValue();
+ final double v2 = o2.getValue();
+ return (goal == GoalType.MINIMIZE) ?
+ Double.compare(v1, v2) : Double.compare(v2, v1);
+ }
+ });
+ }
+}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealOptimizer.java b/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealOptimizer.java
new file mode 100644
index 000000000..383188ead
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealOptimizer.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math.optimization.univariate;
+
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+
+/**
+ * Interface for univariate optimization algorithms.
+ *
+ * @version $Revision$ $Date$
+ * @since 3.0
+ */
+public interface UnivariateRealOptimizer
+ extends BaseUnivariateRealOptimizer {}
diff --git a/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealPointValuePair.java b/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealPointValuePair.java
new file mode 100644
index 000000000..bd742b508
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/optimization/univariate/UnivariateRealPointValuePair.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.optimization.univariate;
+
+import java.io.Serializable;
+
+/**
+ * This class holds a point and the value of an objective function at this
+ * point.
+ * This is a simple immutable container.
+ *
+ * @version $Revision$ $Date$
+ * @since 3.0
+ */
+public class UnivariateRealPointValuePair implements Serializable {
+ /** Serializable version identifier. */
+ private static final long serialVersionUID = 1003888396256744753L;
+ /** Point. */
+ private final double point;
+ /** Value of the objective function at the point. */
+ private final double value;
+
+ /**
+ * Build a point/objective function value pair.
+ *
+ * @param point Point.
+ * @param value Value of an objective function at the point
+ */
+ public UnivariateRealPointValuePair(final double point,
+ final double value) {
+ this.point = point;
+ this.value = value;
+ }
+
+ /**
+ * Get the point.
+ *
+ * @return the point.
+ */
+ public double getPoint() {
+ return point;
+ }
+
+ /**
+ * Get the value of the objective function.
+ *
+ * @return the stored value of the objective function.
+ */
+ public double getValue() {
+ return value;
+ }
+}
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index c81ac94f3..0ae742cfb 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -51,6 +51,17 @@ The type attribute can be add,update,fix,remove.
with a new-line in the release notes. (These spaces are ignored when displaying HTML).
If the output is not quite correct, check for invisible trailing spaces!
-->
+
+
+ Removed methods referring to the concept of "iteration".
+ Removed interface methods to access the number of evaluations of the
+ gradient and Jacobian.
+ Added new "Incrementor" utility to be used as a bounded counter for
+ objective function evaluations.
+ Removed all references to "OptimizationException" (replaced by
+ "ConvergenceException").
+
+
Added faster and more accurate version of traditional mathematical functions in a FastMath
diff --git a/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateRealOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateRealOptimizerTest.java
index 52983eb92..2dc52c557 100644
--- a/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateRealOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateRealOptimizerTest.java
@@ -39,7 +39,7 @@ import org.junit.Test;
public class MultiStartDifferentiableMultivariateRealOptimizerTest {
@Test
- public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
+ public void testCircleFitting() throws FunctionEvaluationException {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@@ -55,14 +55,10 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
new GaussianRandomGenerator(g));
MultiStartDifferentiableMultivariateRealOptimizer optimizer =
new MultiStartDifferentiableMultivariateRealOptimizer(underlying, 10, generator);
- optimizer.setMaxIterations(100);
- assertEquals(100, optimizer.getMaxIterations());
optimizer.setMaxEvaluations(100);
assertEquals(100, optimizer.getMaxEvaluations());
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-10));
BrentSolver solver = new BrentSolver();
- solver.setAbsoluteAccuracy(1.0e-13);
- solver.setRelativeAccuracy(1.0e-15);
RealPointValuePair optimum =
optimizer.optimize(circle, GoalType.MINIMIZE, new double[] { 98.680, 47.345 });
RealPointValuePair[] optima = optimizer.getOptima();
@@ -72,12 +68,8 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
assertEquals(96.075902096, center.x, 1.0e-8);
assertEquals(48.135167894, center.y, 1.0e-8);
}
- assertTrue(optimizer.getGradientEvaluations() > 650);
- assertTrue(optimizer.getGradientEvaluations() < 700);
assertTrue(optimizer.getEvaluations() > 70);
assertTrue(optimizer.getEvaluations() < 90);
- assertTrue(optimizer.getIterations() > 70);
- assertTrue(optimizer.getIterations() < 90);
assertEquals(3.1267527, optimum.getValue(), 1.0e-8);
}
@@ -119,7 +111,6 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
dJdY *= 2;
return new double[] { dJdX, dJdY };
-
}
public double value(double[] variables)
@@ -133,9 +124,7 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
double di = point.distance(center) - radius;
sum += di * di;
}
-
return sum;
-
}
public MultivariateVectorialFunction gradient() {
@@ -153,7 +142,5 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
}
};
}
-
}
-
}
diff --git a/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateVectorialOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateVectorialOptimizerTest.java
index 68c0b64f4..8824c70c1 100644
--- a/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateVectorialOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/MultiStartDifferentiableMultivariateVectorialOptimizerTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.fail;
import java.io.Serializable;
import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.ConvergenceException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.linear.BlockRealMatrix;
@@ -112,7 +113,7 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
10, generator);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
// no optima before first optimization attempt
@@ -134,14 +135,10 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
}
assertTrue(optimizer.getEvaluations() > 20);
assertTrue(optimizer.getEvaluations() < 50);
- assertTrue(optimizer.getIterations() > 20);
- assertTrue(optimizer.getIterations() < 50);
- assertTrue(optimizer.getJacobianEvaluations() > 20);
- assertTrue(optimizer.getJacobianEvaluations() < 50);
- assertEquals(100, optimizer.getMaxIterations());
+ assertEquals(100, optimizer.getMaxEvaluations());
}
- @Test(expected = OptimizationException.class)
+ @Test(expected = ConvergenceException.class)
public void testNoOptimum() throws FunctionEvaluationException, OptimizationException {
DifferentiableMultivariateVectorialOptimizer underlyingOptimizer =
new GaussNewtonOptimizer(true);
@@ -152,7 +149,7 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
10, generator);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
optimizer.optimize(new DifferentiableMultivariateVectorialFunction() {
public MultivariateMatrixFunction jacobian() {
diff --git a/src/test/java/org/apache/commons/math/optimization/MultiStartMultivariateRealOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/MultiStartMultivariateRealOptimizerTest.java
index 2d4ac43d9..385455816 100644
--- a/src/test/java/org/apache/commons/math/optimization/MultiStartMultivariateRealOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/MultiStartMultivariateRealOptimizerTest.java
@@ -48,13 +48,13 @@ public class MultiStartMultivariateRealOptimizerTest {
MultiStartMultivariateRealOptimizer optimizer =
new MultiStartMultivariateRealOptimizer(underlying, 10, generator);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(1100);
RealPointValuePair optimum =
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
- assertTrue(optimizer.getEvaluations() > 20);
- assertTrue(optimizer.getEvaluations() < 250);
+ assertTrue(optimizer.getEvaluations() > 900);
+ assertTrue(optimizer.getEvaluations() < 1200);
assertTrue(optimum.getValue() < 8.0e-4);
}
diff --git a/src/test/java/org/apache/commons/math/optimization/direct/MultiDirectionalTest.java b/src/test/java/org/apache/commons/math/optimization/direct/MultiDirectionalTest.java
index e979654e5..dc2435bf7 100644
--- a/src/test/java/org/apache/commons/math/optimization/direct/MultiDirectionalTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/direct/MultiDirectionalTest.java
@@ -91,7 +91,7 @@ public class MultiDirectionalTest {
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-11, 1.0e-30));
- optimizer.setMaxIterations(200);
+ optimizer.setMaxEvaluations(200);
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
RealPointValuePair optimum;
@@ -146,7 +146,7 @@ public class MultiDirectionalTest {
count = 0;
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setStartConfiguration(new double[][] {
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
});
@@ -180,7 +180,7 @@ public class MultiDirectionalTest {
count = 0;
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
- optimizer.setMaxIterations(1000);
+ optimizer.setMaxEvaluations(1000);
RealPointValuePair optimum =
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
Assert.assertEquals(count, optimizer.getEvaluations());
@@ -196,7 +196,6 @@ public class MultiDirectionalTest {
// fails because MultiDirectional.iterateSimplex is looping forever
// the while(true) should be replaced with a convergence check
MultiDirectional multiDirectional = new MultiDirectional();
- multiDirectional.setMaxIterations(100);
multiDirectional.setMaxEvaluations(1000);
final Gaussian2D function = new Gaussian2D(0.0, 0.0, 1.0);
diff --git a/src/test/java/org/apache/commons/math/optimization/direct/NelderMeadTest.java b/src/test/java/org/apache/commons/math/optimization/direct/NelderMeadTest.java
index 94afc9d45..396d5f881 100644
--- a/src/test/java/org/apache/commons/math/optimization/direct/NelderMeadTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/direct/NelderMeadTest.java
@@ -23,315 +23,278 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.FunctionEvaluationException;
-import org.apache.commons.math.MathException;
-import org.apache.commons.math.MaxEvaluationsExceededException;
-import org.apache.commons.math.MaxIterationsExceededException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.apache.commons.math.analysis.MultivariateRealFunction;
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.LeastSquaresConverter;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.RealPointValuePair;
import org.apache.commons.math.optimization.SimpleRealPointChecker;
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
-import org.apache.commons.math.util.FastMath;
import org.junit.Test;
public class NelderMeadTest {
-
- @Test
- public void testFunctionEvaluationExceptions() {
- MultivariateRealFunction wrong =
- new MultivariateRealFunction() {
- private static final long serialVersionUID = 4751314470965489371L;
- public double value(double[] x) throws FunctionEvaluationException {
- if (x[0] < 0) {
- throw new FunctionEvaluationException(x, "{0}", "oops");
- } else if (x[0] > 1) {
- throw new FunctionEvaluationException(new RuntimeException("oops"), x);
- } else {
- return x[0] * (1 - x[0]);
+ @Test
+ public void testFunctionEvaluationExceptions() {
+ MultivariateRealFunction wrong =
+ new MultivariateRealFunction() {
+ private static final long serialVersionUID = 4751314470965489371L;
+ public double value(double[] x) throws FunctionEvaluationException {
+ if (x[0] < 0) {
+ throw new FunctionEvaluationException(x, "{0}", "oops");
+ } else if (x[0] > 1) {
+ throw new FunctionEvaluationException(new RuntimeException("oops"), x);
+ } else {
+ return x[0] * (1 - x[0]);
+ }
}
- }
- };
- try {
- NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
- optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { -1.0 });
- fail("an exception should have been thrown");
- } catch (FunctionEvaluationException ce) {
- // expected behavior
- assertNull(ce.getCause());
- } catch (Exception e) {
- fail("wrong exception caught: " + e.getMessage());
- }
- try {
- NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
- optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { +2.0 });
- fail("an exception should have been thrown");
- } catch (FunctionEvaluationException ce) {
- // expected behavior
- assertNotNull(ce.getCause());
- } catch (Exception e) {
- fail("wrong exception caught: " + e.getMessage());
- }
- }
+ };
+ try {
+ NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
+ optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { -1.0 });
+ fail("an exception should have been thrown");
+ } catch (FunctionEvaluationException ce) {
+ // expected behavior
+ assertNull(ce.getCause());
+ } catch (Exception e) {
+ fail("wrong exception caught: " + e.getMessage());
+ }
+ try {
+ NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
+ optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { +2.0 });
+ fail("an exception should have been thrown");
+ } catch (FunctionEvaluationException ce) {
+ // expected behavior
+ assertNotNull(ce.getCause());
+ } catch (Exception e) {
+ fail("wrong exception caught: " + e.getMessage());
+ }
+ }
- @Test
- public void testMinimizeMaximize()
- throws FunctionEvaluationException, ConvergenceException {
+ @Test
+ public void testMinimizeMaximize()
+ throws FunctionEvaluationException {
- // the following function has 4 local extrema:
- final double xM = -3.841947088256863675365;
- final double yM = -1.391745200270734924416;
- final double xP = 0.2286682237349059125691;
- final double yP = -yM;
- final double valueXmYm = 0.2373295333134216789769; // local maximum
- final double valueXmYp = -valueXmYm; // local minimum
- final double valueXpYm = -0.7290400707055187115322; // global minimum
- final double valueXpYp = -valueXpYm; // global maximum
- MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
- private static final long serialVersionUID = -7039124064449091152L;
- public double value(double[] variables) throws FunctionEvaluationException {
- final double x = variables[0];
- final double y = variables[1];
- return ((x == 0) || (y == 0)) ? 0 : (FastMath.atan(x) * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y) / (x * y));
- }
- };
+ // the following function has 4 local extrema:
+ final double xM = -3.841947088256863675365;
+ final double yM = -1.391745200270734924416;
+ final double xP = 0.2286682237349059125691;
+ final double yP = -yM;
+ final double valueXmYm = 0.2373295333134216789769; // local maximum
+ final double valueXmYp = -valueXmYm; // local minimum
+ final double valueXpYm = -0.7290400707055187115322; // global minimum
+ final double valueXpYp = -valueXpYm; // global maximum
+ MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
+ private static final long serialVersionUID = -7039124064449091152L;
+ public double value(double[] variables) throws FunctionEvaluationException {
+ final double x = variables[0];
+ final double y = variables[1];
+ return ((x == 0) || (y == 0)) ? 0 : (Math.atan(x) * Math.atan(x + 2) * Math.atan(y) * Math.atan(y) / (x * y));
+ }
+ };
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-30));
- optimizer.setMaxIterations(100);
- optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
- RealPointValuePair optimum;
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-30));
+ optimizer.setMaxEvaluations(100);
+ optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
+ RealPointValuePair optimum;
- // minimization
- optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
- assertEquals(xM, optimum.getPoint()[0], 2.0e-7);
- assertEquals(yP, optimum.getPoint()[1], 2.0e-5);
- assertEquals(valueXmYp, optimum.getValue(), 6.0e-12);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 90);
+ // minimization
+ optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
+ assertEquals(xM, optimum.getPoint()[0], 2.0e-7);
+ assertEquals(yP, optimum.getPoint()[1], 2.0e-5);
+ assertEquals(valueXmYp, optimum.getValue(), 6.0e-12);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 90);
- optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { +1, 0 });
- assertEquals(xP, optimum.getPoint()[0], 5.0e-6);
- assertEquals(yM, optimum.getPoint()[1], 6.0e-6);
- assertEquals(valueXpYm, optimum.getValue(), 1.0e-11);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 90);
+ optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { +1, 0 });
+ assertEquals(xP, optimum.getPoint()[0], 5.0e-6);
+ assertEquals(yM, optimum.getPoint()[1], 6.0e-6);
+ assertEquals(valueXpYm, optimum.getValue(), 1.0e-11);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 90);
- // maximization
- optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
- assertEquals(xM, optimum.getPoint()[0], 1.0e-5);
- assertEquals(yM, optimum.getPoint()[1], 3.0e-6);
- assertEquals(valueXmYm, optimum.getValue(), 3.0e-12);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 90);
+ // maximization
+ optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
+ assertEquals(xM, optimum.getPoint()[0], 1.0e-5);
+ assertEquals(yM, optimum.getPoint()[1], 3.0e-6);
+ assertEquals(valueXmYm, optimum.getValue(), 3.0e-12);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 90);
- optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { +1, 0 });
- assertEquals(xP, optimum.getPoint()[0], 4.0e-6);
- assertEquals(yP, optimum.getPoint()[1], 5.0e-6);
- assertEquals(valueXpYp, optimum.getValue(), 7.0e-12);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 90);
+ optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { +1, 0 });
+ assertEquals(xP, optimum.getPoint()[0], 4.0e-6);
+ assertEquals(yP, optimum.getPoint()[1], 5.0e-6);
+ assertEquals(valueXpYp, optimum.getValue(), 7.0e-12);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 90);
+ }
- }
+ @Test
+ public void testRosenbrock()
+ throws FunctionEvaluationException {
- @Test
- public void testRosenbrock()
- throws FunctionEvaluationException, ConvergenceException {
+ Rosenbrock rosenbrock = new Rosenbrock();
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
+ optimizer.setMaxEvaluations(100);
+ optimizer.setStartConfiguration(new double[][] {
+ { -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
+ });
+ RealPointValuePair optimum =
+ optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
- Rosenbrock rosenbrock = new Rosenbrock();
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
- optimizer.setMaxIterations(100);
- optimizer.setStartConfiguration(new double[][] {
- { -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
- });
- RealPointValuePair optimum =
- optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
+ assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
+ assertTrue(optimizer.getEvaluations() > 40);
+ assertTrue(optimizer.getEvaluations() < 50);
+ assertTrue(optimum.getValue() < 8.0e-4);
+ }
- assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
- assertTrue(optimizer.getEvaluations() > 40);
- assertTrue(optimizer.getEvaluations() < 50);
- assertTrue(optimum.getValue() < 8.0e-4);
+ @Test
+ public void testPowell()
+ throws FunctionEvaluationException {
- }
+ Powell powell = new Powell();
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
+ optimizer.setMaxEvaluations(200);
+ RealPointValuePair optimum =
+ optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
+ assertEquals(powell.getCount(), optimizer.getEvaluations());
+ assertTrue(optimizer.getEvaluations() > 110);
+ assertTrue(optimizer.getEvaluations() < 130);
+ assertTrue(optimum.getValue() < 2.0e-3);
+ }
- @Test
- public void testPowell()
- throws FunctionEvaluationException, ConvergenceException {
+ @Test
+ public void testLeastSquares1()
+ throws FunctionEvaluationException {
- Powell powell = new Powell();
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
- optimizer.setMaxIterations(200);
- RealPointValuePair optimum =
- optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
- assertEquals(powell.getCount(), optimizer.getEvaluations());
- assertTrue(optimizer.getEvaluations() > 110);
- assertTrue(optimizer.getEvaluations() < 130);
- assertTrue(optimum.getValue() < 2.0e-3);
+ final RealMatrix factors =
+ new Array2DRowRealMatrix(new double[][] {
+ { 1.0, 0.0 },
+ { 0.0, 1.0 }
+ }, false);
+ LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
+ public double[] value(double[] variables) {
+ return factors.operate(variables);
+ }
+ }, new double[] { 2.0, -3.0 });
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
+ optimizer.setMaxEvaluations(200);
+ RealPointValuePair optimum =
+ optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
+ assertEquals( 2.0, optimum.getPointRef()[0], 3.0e-5);
+ assertEquals(-3.0, optimum.getPointRef()[1], 4.0e-4);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 80);
+ assertTrue(optimum.getValue() < 1.0e-6);
+ }
- }
+ @Test
+ public void testLeastSquares2()
+ throws FunctionEvaluationException {
- @Test
- public void testLeastSquares1()
- throws FunctionEvaluationException, ConvergenceException {
+ final RealMatrix factors =
+ new Array2DRowRealMatrix(new double[][] {
+ { 1.0, 0.0 },
+ { 0.0, 1.0 }
+ }, false);
+ LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
+ public double[] value(double[] variables) {
+ return factors.operate(variables);
+ }
+ }, new double[] { 2.0, -3.0 }, new double[] { 10.0, 0.1 });
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
+ optimizer.setMaxEvaluations(200);
+ RealPointValuePair optimum =
+ optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
+ assertEquals( 2.0, optimum.getPointRef()[0], 5.0e-5);
+ assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 80);
+ assertTrue(optimum.getValue() < 1.0e-6);
+ }
- final RealMatrix factors =
- new Array2DRowRealMatrix(new double[][] {
- { 1.0, 0.0 },
- { 0.0, 1.0 }
- }, false);
- LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
- public double[] value(double[] variables) {
- return factors.operate(variables);
- }
- }, new double[] { 2.0, -3.0 });
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
- optimizer.setMaxIterations(200);
- RealPointValuePair optimum =
- optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
- assertEquals( 2.0, optimum.getPointRef()[0], 3.0e-5);
- assertEquals(-3.0, optimum.getPointRef()[1], 4.0e-4);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 80);
- assertTrue(optimum.getValue() < 1.0e-6);
- }
+ @Test
+ public void testLeastSquares3()
+ throws FunctionEvaluationException {
- @Test
- public void testLeastSquares2()
- throws FunctionEvaluationException, ConvergenceException {
+ final RealMatrix factors =
+ new Array2DRowRealMatrix(new double[][] {
+ { 1.0, 0.0 },
+ { 0.0, 1.0 }
+ }, false);
+ LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
+ public double[] value(double[] variables) {
+ return factors.operate(variables);
+ }
+ }, new double[] { 2.0, -3.0 }, new Array2DRowRealMatrix(new double [][] {
+ { 1.0, 1.2 }, { 1.2, 2.0 }
+ }));
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
+ optimizer.setMaxEvaluations(200);
+ RealPointValuePair optimum =
+ optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
+ assertEquals( 2.0, optimum.getPointRef()[0], 2.0e-3);
+ assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
+ assertTrue(optimizer.getEvaluations() > 60);
+ assertTrue(optimizer.getEvaluations() < 80);
+ assertTrue(optimum.getValue() < 1.0e-6);
+ }
- final RealMatrix factors =
- new Array2DRowRealMatrix(new double[][] {
- { 1.0, 0.0 },
- { 0.0, 1.0 }
- }, false);
- LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
- public double[] value(double[] variables) {
- return factors.operate(variables);
- }
- }, new double[] { 2.0, -3.0 }, new double[] { 10.0, 0.1 });
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
- optimizer.setMaxIterations(200);
- RealPointValuePair optimum =
- optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
- assertEquals( 2.0, optimum.getPointRef()[0], 5.0e-5);
- assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 80);
- assertTrue(optimum.getValue() < 1.0e-6);
- }
+ @Test(expected = TooManyEvaluationsException.class)
+ public void testMaxIterations() throws FunctionEvaluationException {
+ Powell powell = new Powell();
+ NelderMead optimizer = new NelderMead();
+ optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
+ optimizer.setMaxEvaluations(20);
+ optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
+ }
- @Test
- public void testLeastSquares3()
- throws FunctionEvaluationException, ConvergenceException {
+ private static class Rosenbrock implements MultivariateRealFunction {
+ private int count;
- final RealMatrix factors =
- new Array2DRowRealMatrix(new double[][] {
- { 1.0, 0.0 },
- { 0.0, 1.0 }
- }, false);
- LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
- public double[] value(double[] variables) {
- return factors.operate(variables);
- }
- }, new double[] { 2.0, -3.0 }, new Array2DRowRealMatrix(new double [][] {
- { 1.0, 1.2 }, { 1.2, 2.0 }
- }));
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
- optimizer.setMaxIterations(200);
- RealPointValuePair optimum =
- optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
- assertEquals( 2.0, optimum.getPointRef()[0], 2.0e-3);
- assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
- assertTrue(optimizer.getEvaluations() > 60);
- assertTrue(optimizer.getEvaluations() < 80);
- assertTrue(optimum.getValue() < 1.0e-6);
- }
+ public Rosenbrock() {
+ count = 0;
+ }
- @Test(expected = MaxIterationsExceededException.class)
- public void testMaxIterations() throws MathException {
- try {
- Powell powell = new Powell();
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
- optimizer.setMaxIterations(20);
- optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
- } catch (OptimizationException oe) {
- if (oe.getCause() instanceof ConvergenceException) {
- throw (ConvergenceException) oe.getCause();
- }
- throw oe;
- }
- }
+ public double value(double[] x) throws FunctionEvaluationException {
+ ++count;
+ double a = x[1] - x[0] * x[0];
+ double b = 1.0 - x[0];
+ return 100 * a * a + b * b;
+ }
- @Test(expected = MaxEvaluationsExceededException.class)
- public void testMaxEvaluations() throws MathException {
- try {
- Powell powell = new Powell();
- NelderMead optimizer = new NelderMead();
- optimizer.setConvergenceChecker(new SimpleRealPointChecker(-1.0, 1.0e-3));
- optimizer.setMaxEvaluations(20);
- optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
- } catch (FunctionEvaluationException fee) {
- if (fee.getCause() instanceof ConvergenceException) {
- throw (ConvergenceException) fee.getCause();
- }
- throw fee;
- }
- }
+ public int getCount() {
+ return count;
+ }
+ }
- private static class Rosenbrock implements MultivariateRealFunction {
+ private static class Powell implements MultivariateRealFunction {
+ private int count;
- private int count;
+ public Powell() {
+ count = 0;
+ }
- public Rosenbrock() {
- count = 0;
- }
-
- public double value(double[] x) throws FunctionEvaluationException {
- ++count;
- double a = x[1] - x[0] * x[0];
- double b = 1.0 - x[0];
- return 100 * a * a + b * b;
- }
-
- public int getCount() {
- return count;
- }
-
- }
-
- private static class Powell implements MultivariateRealFunction {
-
- private int count;
-
- public Powell() {
- count = 0;
- }
-
- public double value(double[] x) throws FunctionEvaluationException {
- ++count;
- double a = x[0] + 10 * x[1];
- double b = x[2] - x[3];
- double c = x[1] - 2 * x[2];
- double d = x[0] - x[3];
- return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
- }
-
- public int getCount() {
- return count;
- }
-
- }
+ public double value(double[] x) throws FunctionEvaluationException {
+ ++count;
+ double a = x[0] + 10 * x[1];
+ double b = x[2] - x[3];
+ double c = x[1] - 2 * x[2];
+ double d = x[0] - x[3];
+ return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
+ }
+ public int getCount() {
+ return count;
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/math/optimization/fitting/PolynomialFitterTest.java b/src/test/java/org/apache/commons/math/optimization/fitting/PolynomialFitterTest.java
index fe85640ef..2c6af100a 100644
--- a/src/test/java/org/apache/commons/math/optimization/fitting/PolynomialFitterTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/fitting/PolynomialFitterTest.java
@@ -23,8 +23,8 @@ import static org.junit.Assert.assertTrue;
import java.util.Random;
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
+import org.apache.commons.math.exception.ConvergenceException;
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
import org.apache.commons.math.util.FastMath;
@@ -33,7 +33,7 @@ import org.junit.Test;
public class PolynomialFitterTest {
@Test
- public void testNoError() throws OptimizationException {
+ public void testNoError() {
Random randomizer = new Random(64925784252l);
for (int degree = 1; degree < 10; ++degree) {
PolynomialFunction p = buildRandomPolynomial(degree, randomizer);
@@ -57,7 +57,7 @@ public class PolynomialFitterTest {
}
@Test
- public void testSmallError() throws OptimizationException {
+ public void testSmallError() {
Random randomizer = new Random(53882150042l);
double maxError = 0;
for (int degree = 0; degree < 10; ++degree) {
@@ -116,7 +116,7 @@ public class PolynomialFitterTest {
try {
fitter.fit();
assertTrue(solvable || (degree == 0));
- } catch(OptimizationException e) {
+ } catch(ConvergenceException e) {
assertTrue((! solvable) && (degree > 0));
}
diff --git a/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java
index dcdbec34c..d121e5ab3 100644
--- a/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java
@@ -25,11 +25,13 @@ import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.ConvergenceException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
+import org.apache.commons.math.exception.DimensionMismatchException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.linear.BlockRealMatrix;
import org.apache.commons.math.linear.RealMatrix;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialPointChecker;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialPointValuePair;
@@ -104,11 +106,11 @@ extends TestCase {
super(name);
}
- public void testTrivial() throws FunctionEvaluationException, OptimizationException {
+ public void testTrivial() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1 }, new double[] { 0 });
@@ -117,14 +119,14 @@ extends TestCase {
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
}
- public void testColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
+ public void testColumnsPermutation() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } },
new double[] { 4.0, 6.0, 1.0 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0 });
@@ -137,7 +139,7 @@ extends TestCase {
}
- public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
+ public void testNoDependency() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 },
{ 0, 2, 0, 0, 0, 0 },
@@ -147,7 +149,7 @@ extends TestCase {
{ 0, 0, 0, 0, 0, 2 }
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
@@ -158,7 +160,7 @@ extends TestCase {
}
}
- public void testOneSet() throws FunctionEvaluationException, OptimizationException {
+ public void testOneSet() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 },
@@ -166,7 +168,7 @@ extends TestCase {
{ 0, -1, 1 }
}, new double[] { 1, 1, 1});
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
@@ -177,7 +179,7 @@ extends TestCase {
}
- public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
+ public void testTwoSets() throws FunctionEvaluationException {
double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 },
@@ -189,7 +191,7 @@ extends TestCase {
}, new double[] { 2, -9, 2, 2, 1 + epsilon * epsilon, 2});
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
@@ -212,19 +214,19 @@ extends TestCase {
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
try {
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
fail("an exception should have been caught");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception type caught");
}
}
- public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
+ public void testIllConditioned() throws FunctionEvaluationException {
LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.0 },
@@ -232,7 +234,7 @@ extends TestCase {
{ 7.0, 5.0, 9.0, 10.0 }
}, new double[] { 32, 23, 33, 31 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum1 =
optimizer.optimize(problem1, problem1.target, new double[] { 1, 1, 1, 1 },
@@ -269,13 +271,13 @@ extends TestCase {
}, new double[] { 7.0, 3.0, 5.0 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
try {
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
new double[] { 7, 6, 5, 4 });
fail("an exception should have been caught");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception type caught");
@@ -292,20 +294,20 @@ extends TestCase {
{ 0.0, 0.0, 0.0, -1.0, 1.0, 0.0 }
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
try {
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1 },
new double[] { 2, 2, 2, 2, 2, 2 });
fail("an exception should have been caught");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception type caught");
}
}
- public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
+ public void testRedundantEquations() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@@ -313,7 +315,7 @@ extends TestCase {
}, new double[] { 3.0, 1.0, 5.0 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
@@ -324,7 +326,7 @@ extends TestCase {
}
- public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
+ public void testInconsistentEquations() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@@ -332,18 +334,18 @@ extends TestCase {
}, new double[] { 3.0, 1.0, 4.0 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 1, 1 });
assertTrue(optimizer.getRMS() > 0.1);
}
- public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
+ public void testInconsistentSizes() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
VectorialPointValuePair optimum =
@@ -357,7 +359,7 @@ extends TestCase {
new double[] { 1 },
new double[] { 0, 0 });
fail("an exception should have been thrown");
- } catch (OptimizationException oe) {
+ } catch (DimensionMismatchException oe) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@@ -376,7 +378,7 @@ extends TestCase {
}
- public void testMaxIterations() {
+ public void testMaxEvaluations() {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@@ -384,21 +386,21 @@ extends TestCase {
circle.addPoint( 35.0, 15.0);
circle.addPoint( 45.0, 97.0);
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialPointChecker(1.0e-30, 1.0e-30));
try {
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
new double[] { 1, 1, 1, 1, 1 },
new double[] { 98.680, 47.345 });
fail("an exception should have been caught");
- } catch (OptimizationException ee) {
+ } catch (TooManyEvaluationsException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception type caught");
}
}
- public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
+ public void testCircleFitting() throws FunctionEvaluationException {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@@ -406,7 +408,7 @@ extends TestCase {
circle.addPoint( 35.0, 15.0);
circle.addPoint( 45.0, 97.0);
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-13, 1.0e-13));
VectorialPointValuePair optimum =
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
@@ -419,7 +421,7 @@ extends TestCase {
assertEquals(48.135167894714, center.y, 1.0e-10);
}
- public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
+ public void testCircleFittingBadInit() throws FunctionEvaluationException {
Circle circle = new Circle();
double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724},
@@ -460,12 +462,12 @@ extends TestCase {
circle.addPoint(points[i][0], points[i][1]);
}
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
try {
optimizer.optimize(circle, target, weights, new double[] { -12, -12 });
fail("an exception should have been caught");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception type caught");
diff --git a/src/test/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizerTest.java
index b75b7e324..f80dc460b 100644
--- a/src/test/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizerTest.java
@@ -26,11 +26,13 @@ import java.util.List;
import junit.framework.TestCase;
import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.ConvergenceException;
+import org.apache.commons.math.exception.DimensionMismatchException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.linear.BlockRealMatrix;
import org.apache.commons.math.linear.RealMatrix;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialPointValuePair;
import org.apache.commons.math.util.FastMath;
@@ -104,7 +106,7 @@ public class LevenbergMarquardtOptimizerTest
super(name);
}
- public void testTrivial() throws FunctionEvaluationException, OptimizationException {
+ public void testTrivial() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@@ -114,7 +116,7 @@ public class LevenbergMarquardtOptimizerTest
try {
optimizer.guessParametersErrors();
fail("an exception should have been thrown");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@@ -123,7 +125,7 @@ public class LevenbergMarquardtOptimizerTest
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
}
- public void testQRColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
+ public void testQRColumnsPermutation() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } },
@@ -141,7 +143,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
+ public void testNoDependency() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 },
{ 0, 2, 0, 0, 0, 0 },
@@ -160,7 +162,7 @@ public class LevenbergMarquardtOptimizerTest
}
}
- public void testOneSet() throws FunctionEvaluationException, OptimizationException {
+ public void testOneSet() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 },
@@ -177,7 +179,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
+ public void testTwoSets() throws FunctionEvaluationException {
double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 },
@@ -202,7 +204,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testNonInversible() throws FunctionEvaluationException, OptimizationException {
+ public void testNonInversible() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
@@ -216,7 +218,7 @@ public class LevenbergMarquardtOptimizerTest
try {
optimizer.getCovariances();
fail("an exception should have been thrown");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@@ -224,7 +226,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
+ public void testIllConditioned() throws FunctionEvaluationException {
LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.0 },
@@ -258,7 +260,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testMoreEstimatedParametersSimple() throws FunctionEvaluationException, OptimizationException {
+ public void testMoreEstimatedParametersSimple() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 3.0, 2.0, 0.0, 0.0 },
@@ -273,7 +275,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testMoreEstimatedParametersUnsorted() throws FunctionEvaluationException, OptimizationException {
+ public void testMoreEstimatedParametersUnsorted() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0, 1.0, 1.0, 0.0 },
@@ -294,7 +296,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
+ public void testRedundantEquations() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@@ -311,7 +313,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
+ public void testInconsistentEquations() throws FunctionEvaluationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@@ -324,7 +326,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
+ public void testInconsistentSizes() throws FunctionEvaluationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@@ -340,7 +342,7 @@ public class LevenbergMarquardtOptimizerTest
new double[] { 1 },
new double[] { 0, 0 });
fail("an exception should have been thrown");
- } catch (OptimizationException oe) {
+ } catch (DimensionMismatchException oe) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@@ -380,23 +382,23 @@ public class LevenbergMarquardtOptimizerTest
try {
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
optimizer.setInitialStepBoundFactor(initialStepBoundFactor);
- optimizer.setMaxIterations(maxCostEval);
+ optimizer.setMaxEvaluations(maxCostEval);
optimizer.setCostRelativeTolerance(costRelativeTolerance);
optimizer.setParRelativeTolerance(parRelativeTolerance);
optimizer.setOrthoTolerance(orthoTolerance);
optimizer.optimize(problem, new double[] { 0, 0, 0, 0, 0 }, new double[] { 1, 1, 1, 1, 1 },
new double[] { 98.680, 47.345 });
- assertTrue(! shouldFail);
- } catch (OptimizationException ee) {
- assertTrue(shouldFail);
+ assertTrue(!shouldFail);
} catch (FunctionEvaluationException ee) {
assertTrue(shouldFail);
+ } catch (TooManyEvaluationsException ee) {
+ assertTrue(shouldFail);
} catch (Exception e) {
fail("wrong exception type caught");
}
}
- public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
+ public void testCircleFitting() throws FunctionEvaluationException {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@@ -445,7 +447,7 @@ public class LevenbergMarquardtOptimizerTest
}
- public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
+ public void testCircleFittingBadInit() throws FunctionEvaluationException {
Circle circle = new Circle();
double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724},
@@ -513,7 +515,7 @@ public class LevenbergMarquardtOptimizerTest
new double[] { 0.0, 4.4e-323, 1.0, 4.4e-323, 0.0 },
new double[] { 0, 0, 0 });
fail("an exception should have been thrown");
- } catch (OptimizationException ee) {
+ } catch (ConvergenceException ee) {
// expected behavior
}
diff --git a/src/test/java/org/apache/commons/math/optimization/general/MinpackTest.java b/src/test/java/org/apache/commons/math/optimization/general/MinpackTest.java
index a63162c52..f6404eb46 100644
--- a/src/test/java/org/apache/commons/math/optimization/general/MinpackTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/general/MinpackTest.java
@@ -23,9 +23,9 @@ import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
-import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.VectorialPointValuePair;
import org.apache.commons.math.util.FastMath;
@@ -490,7 +490,7 @@ public class MinpackTest extends TestCase {
private void minpackTest(MinpackFunction function, boolean exceptionExpected) {
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
- optimizer.setMaxIterations(100 * (function.getN() + 1));
+ optimizer.setMaxEvaluations(400 * (function.getN() + 1));
optimizer.setCostRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
optimizer.setParRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
optimizer.setOrthoTolerance(2.22044604926e-16);
@@ -503,7 +503,7 @@ public class MinpackTest extends TestCase {
assertFalse(exceptionExpected);
function.checkTheoreticalMinCost(optimizer.getRMS());
function.checkTheoreticalMinParams(optimum);
- } catch (OptimizationException lsse) {
+ } catch (TooManyEvaluationsException e) {
assertTrue(exceptionExpected);
} catch (FunctionEvaluationException fe) {
assertTrue(exceptionExpected);
diff --git a/src/test/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizerTest.java
index ec49bc631..8fb034ef7 100644
--- a/src/test/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/general/NonLinearConjugateGradientOptimizerTest.java
@@ -109,7 +109,7 @@ extends TestCase {
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0 });
@@ -125,7 +125,7 @@ extends TestCase {
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0 });
@@ -146,7 +146,7 @@ extends TestCase {
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0, 0, 0, 0 });
@@ -164,7 +164,7 @@ extends TestCase {
}, new double[] { 1, 1, 1});
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
@@ -187,7 +187,7 @@ extends TestCase {
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setPreconditioner(new Preconditioner() {
public double[] precondition(double[] point, double[] r) {
double[] d = r.clone();
@@ -222,7 +222,7 @@ extends TestCase {
}, new double[] { 1, 1, 1 });
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
@@ -238,7 +238,7 @@ extends TestCase {
}, new double[] { 32, 23, 33, 31 });
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-13, 1.0e-13));
BrentSolver solver = new BrentSolver();
solver.setAbsoluteAccuracy(1.0e-15);
@@ -277,7 +277,7 @@ extends TestCase {
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 7, 6, 5, 4 });
@@ -296,7 +296,7 @@ extends TestCase {
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 2, 2, 2, 2, 2, 2 });
@@ -312,7 +312,7 @@ extends TestCase {
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
@@ -330,7 +330,7 @@ extends TestCase {
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
RealPointValuePair optimum =
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
@@ -347,7 +347,7 @@ extends TestCase {
circle.addPoint( 45.0, 97.0);
NonLinearConjugateGradientOptimizer optimizer =
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
- optimizer.setMaxIterations(100);
+ optimizer.setMaxEvaluations(100);
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-30, 1.0e-30));
BrentSolver solver = new BrentSolver();
solver.setAbsoluteAccuracy(1.0e-13);
diff --git a/src/test/java/org/apache/commons/math/optimization/general/PowellOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/general/PowellOptimizerTest.java
index bd34b98db..9a8ece534 100644
--- a/src/test/java/org/apache/commons/math/optimization/general/PowellOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/general/PowellOptimizerTest.java
@@ -48,13 +48,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) {
init[i] = minPoint[i];
}
- // doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
+ doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7);
// Initial is far from minimum.
for (int i = 0; i < dim; i++) {
init[i] = minPoint[i] + 3;
}
- doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
+ doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7);
}
@Test
@@ -80,13 +80,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) {
init[i] = minPoint[i];
}
- doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
+ doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
// Initial is far from minimum.
for (int i = 0; i < dim; i++) {
init[i] = minPoint[i] - 20;
}
- doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
+ doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
}
@Test
@@ -112,13 +112,13 @@ public class PowellOptimizerTest {
for (int i = 0; i < dim; i++) {
init[i] = maxPoint[i];
}
- doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
+ doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
// Initial is far from minimum.
for (int i = 0; i < dim; i++) {
init[i] = maxPoint[i] - 20;
}
- doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
+ doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
}
/**
@@ -126,8 +126,6 @@ public class PowellOptimizerTest {
* @param optimum Expected optimum.
* @param init Starting point.
* @param goal Minimization or maximization.
- * @param xTol Tolerance (relative error on the objective function) for
- * "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.
@@ -136,12 +134,12 @@ public class PowellOptimizerTest {
double[] optimum,
double[] init,
GoalType goal,
- double xTol,
double fTol,
double pointTol)
throws MathException {
- final MultivariateRealOptimizer optim = new PowellOptimizer(xTol);
- optim.setConvergenceChecker(new SimpleScalarValueChecker(fTol, -1));
+ final MultivariateRealOptimizer optim = new PowellOptimizer();
+ optim.setMaxEvaluations(1000);
+ optim.setConvergenceChecker(new SimpleScalarValueChecker(fTol, Math.ulp(1d)));
final RealPointValuePair result = optim.optimize(func, goal, init);
final double[] found = result.getPoint();
diff --git a/src/test/java/org/apache/commons/math/optimization/univariate/BracketFinderTest.java b/src/test/java/org/apache/commons/math/optimization/univariate/BracketFinderTest.java
index 984c60bd6..405e318cc 100644
--- a/src/test/java/org/apache/commons/math/optimization/univariate/BracketFinderTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/univariate/BracketFinderTest.java
@@ -24,6 +24,9 @@ import org.apache.commons.math.optimization.GoalType;
import org.junit.Assert;
import org.junit.Test;
+/**
+ * Test for {@link BracketFinder}.
+ */
public class BracketFinderTest {
@Test
@@ -70,4 +73,52 @@ public class BracketFinderTest {
Assert.assertEquals(-1, bFind.getMid(), tol);
Assert.assertEquals(0.61803399999999997, bFind.getHi(), tol);
}
+
+ @Test
+ public void testMinimumIsOnIntervalBoundary() throws MathException {
+ final UnivariateRealFunction func = new UnivariateRealFunction() {
+ public double value(double x)
+ throws FunctionEvaluationException {
+ return x * x;
+ }
+ };
+
+ final BracketFinder bFind = new BracketFinder();
+
+ bFind.search(func, GoalType.MINIMIZE, 0, 1);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+
+ bFind.search(func, GoalType.MINIMIZE, -1, 0);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+ }
+
+ @Test
+ public void testIntervalBoundsOrdering() throws MathException {
+ final UnivariateRealFunction func = new UnivariateRealFunction() {
+ public double value(double x)
+ throws FunctionEvaluationException {
+ return x * x;
+ }
+ };
+
+ final BracketFinder bFind = new BracketFinder();
+
+ bFind.search(func, GoalType.MINIMIZE, -1, 1);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+
+ bFind.search(func, GoalType.MINIMIZE, 1, -1);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+
+ bFind.search(func, GoalType.MINIMIZE, 1, 2);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+
+ bFind.search(func, GoalType.MINIMIZE, 2, 1);
+ Assert.assertTrue(bFind.getLo() <= 0);
+ Assert.assertTrue(0 <= bFind.getHi());
+ }
}
diff --git a/src/test/java/org/apache/commons/math/optimization/univariate/BrentOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/univariate/BrentOptimizerTest.java
index e0679eab2..8b747d0a1 100644
--- a/src/test/java/org/apache/commons/math/optimization/univariate/BrentOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/univariate/BrentOptimizerTest.java
@@ -20,17 +20,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathException;
-import org.apache.commons.math.MaxIterationsExceededException;
-import org.apache.commons.math.exception.NoDataException;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.apache.commons.math.analysis.QuinticFunction;
import org.apache.commons.math.analysis.SinFunction;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.optimization.GoalType;
-import org.apache.commons.math.optimization.UnivariateRealOptimizer;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
-import org.apache.commons.math.util.FastMath;
import org.junit.Test;
/**
@@ -41,28 +38,22 @@ public final class BrentOptimizerTest {
@Test
public void testSinMin() throws MathException {
UnivariateRealFunction f = new SinFunction();
- UnivariateRealOptimizer minimizer = new BrentOptimizer();
- minimizer.setMaxEvaluations(200);
- assertEquals(200, minimizer.getMaxEvaluations());
+ UnivariateRealOptimizer optimizer = new BrentOptimizer();
+ optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
+ optimizer.setMaxEvaluations(200);
+ assertEquals(200, optimizer.getMaxEvaluations());
+ assertEquals(3 * Math.PI / 2, optimizer.optimize(f, GoalType.MINIMIZE, 4, 5).getPoint(),
+ 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
+ assertTrue(optimizer.getEvaluations() <= 50);
+ assertEquals(3 * Math.PI / 2, optimizer.optimize(f, GoalType.MINIMIZE, 1, 5).getPoint(),
+ 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
+ assertTrue(optimizer.getEvaluations() <= 100);
+ assertTrue(optimizer.getEvaluations() >= 15);
+ optimizer.setMaxEvaluations(10);
try {
- minimizer.getResult();
+ optimizer.optimize(f, GoalType.MINIMIZE, 4, 5);
fail("an exception should have been thrown");
- } catch (NoDataException ise) {
- // expected
- } catch (Exception e) {
- fail("wrong exception caught");
- }
- assertEquals(3 * FastMath.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 4, 5), 10 * minimizer.getRelativeAccuracy());
- assertTrue(minimizer.getIterationCount() <= 50);
- assertEquals(3 * FastMath.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 1, 5), 10 * minimizer.getRelativeAccuracy());
- assertTrue(minimizer.getIterationCount() <= 50);
- assertTrue(minimizer.getEvaluations() <= 100);
- assertTrue(minimizer.getEvaluations() >= 15);
- minimizer.setMaxEvaluations(10);
- try {
- minimizer.optimize(f, GoalType.MINIMIZE, 4, 5);
- fail("an exception should have been thrown");
- } catch (FunctionEvaluationException fee) {
+ } catch (TooManyEvaluationsException fee) {
// expected
} catch (Exception e) {
fail("wrong exception caught");
@@ -73,25 +64,27 @@ public final class BrentOptimizerTest {
public void testQuinticMin() throws MathException {
// The function has local minima at -0.27195613 and 0.82221643.
UnivariateRealFunction f = new QuinticFunction();
- UnivariateRealOptimizer minimizer = new BrentOptimizer();
- assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2), 1.0e-8);
- assertEquals( 0.82221643, minimizer.optimize(f, GoalType.MINIMIZE, 0.3, 0.9), 1.0e-8);
- assertTrue(minimizer.getIterationCount() <= 50);
+ UnivariateRealOptimizer optimizer = new BrentOptimizer();
+ optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
+ optimizer.setMaxEvaluations(200);
+ assertEquals(-0.27195613, optimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2).getPoint(), 1.0e-8);
+ assertEquals( 0.82221643, optimizer.optimize(f, GoalType.MINIMIZE, 0.3, 0.9).getPoint(), 1.0e-8);
+ assertTrue(optimizer.getEvaluations() <= 50);
// search in a large interval
- assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -1.0, 0.2), 1.0e-8);
- assertTrue(minimizer.getIterationCount() <= 50);
+ assertEquals(-0.27195613, optimizer.optimize(f, GoalType.MINIMIZE, -1.0, 0.2).getPoint(), 1.0e-8);
+ assertTrue(optimizer.getEvaluations() <= 50);
}
@Test
public void testQuinticMinStatistics() throws MathException {
// The function has local minima at -0.27195613 and 0.82221643.
UnivariateRealFunction f = new QuinticFunction();
- UnivariateRealOptimizer minimizer = new BrentOptimizer();
- minimizer.setRelativeAccuracy(1e-10);
- minimizer.setAbsoluteAccuracy(1e-11);
+ UnivariateRealOptimizer optimizer = new BrentOptimizer();
+ optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-12, 1e-14));
+ optimizer.setMaxEvaluations(40);
- final DescriptiveStatistics[] stat = new DescriptiveStatistics[3];
+ final DescriptiveStatistics[] stat = new DescriptiveStatistics[2];
for (int i = 0; i < stat.length; i++) {
stat[i] = new DescriptiveStatistics();
}
@@ -102,31 +95,29 @@ public final class BrentOptimizerTest {
final double delta = (max - min) / nSamples;
for (int i = 0; i < nSamples; i++) {
final double start = min + i * delta;
- stat[0].addValue(minimizer.optimize(f, GoalType.MINIMIZE, min, max, start));
- stat[1].addValue(minimizer.getIterationCount());
- stat[2].addValue(minimizer.getEvaluations());
+ stat[0].addValue(optimizer.optimize(f, GoalType.MINIMIZE, min, max, start).getPoint());
+ stat[1].addValue(optimizer.getEvaluations());
}
final double meanOptValue = stat[0].getMean();
- final double medianIter = stat[1].getPercentile(50);
- final double medianEval = stat[2].getPercentile(50);
- assertTrue(meanOptValue > -0.27195612812 && meanOptValue < -0.27195612811);
- assertEquals(medianIter, 17, FastMath.ulp(1d));
- assertEquals(medianEval, 18, FastMath.ulp(1d));
+ final double medianEval = stat[1].getPercentile(50);
+ assertTrue(meanOptValue > -0.2719561281 && meanOptValue < -0.2719561280);
+ assertEquals((int) medianEval, 27);
}
- @Test
+ @Test(expected = TooManyEvaluationsException.class)
public void testQuinticMax() throws MathException {
// The quintic function has zeros at 0, +-0.5 and +-1.
// The function has a local maximum at 0.27195613.
UnivariateRealFunction f = new QuinticFunction();
- UnivariateRealOptimizer minimizer = new BrentOptimizer();
- assertEquals(0.27195613, minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3), 1.0e-8);
- minimizer.setMaximalIterationCount(5);
+ UnivariateRealOptimizer optimizer = new BrentOptimizer();
+ optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-12, 1e-14));
+ assertEquals(0.27195613, optimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3).getPoint(), 1e-8);
+ optimizer.setMaxEvaluations(5);
try {
- minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3);
+ optimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3);
fail("an exception should have been thrown");
- } catch (MaxIterationsExceededException miee) {
+ } catch (TooManyEvaluationsException miee) {
// expected
} catch (Exception e) {
fail("wrong exception caught");
@@ -136,15 +127,15 @@ public final class BrentOptimizerTest {
@Test
public void testMinEndpoints() throws Exception {
UnivariateRealFunction f = new SinFunction();
- UnivariateRealOptimizer solver = new BrentOptimizer();
-
- solver.setRelativeAccuracy(1e-8);
+ UnivariateRealOptimizer optimizer = new BrentOptimizer();
+ optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-8, 1e-14));
+ optimizer.setMaxEvaluations(50);
// endpoint is minimum
- double result = solver.optimize(f, GoalType.MINIMIZE, 3 * FastMath.PI / 2, 5);
- assertEquals(3 * FastMath.PI / 2, result, 10 * solver.getRelativeAccuracy());
+ double result = optimizer.optimize(f, GoalType.MINIMIZE, 3 * Math.PI / 2, 5).getPoint();
+ assertEquals(3 * Math.PI / 2, result, 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
- result = solver.optimize(f, GoalType.MINIMIZE, 4, 3 * FastMath.PI / 2);
- assertEquals(3 * FastMath.PI / 2, result, 10 * solver.getRelativeAccuracy());
+ result = optimizer.optimize(f, GoalType.MINIMIZE, 4, 3 * Math.PI / 2).getPoint();
+ assertEquals(3 * Math.PI / 2, result, 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
}
}
diff --git a/src/test/java/org/apache/commons/math/optimization/MultiStartUnivariateRealOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizerTest.java
similarity index 54%
rename from src/test/java/org/apache/commons/math/optimization/MultiStartUnivariateRealOptimizerTest.java
rename to src/test/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizerTest.java
index df5403c16..47864e2a6 100644
--- a/src/test/java/org/apache/commons/math/optimization/MultiStartUnivariateRealOptimizerTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/univariate/MultiStartUnivariateRealOptimizerTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.commons.math.optimization;
+package org.apache.commons.math.optimization.univariate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -26,6 +26,7 @@ import org.apache.commons.math.analysis.QuinticFunction;
import org.apache.commons.math.analysis.SinFunction;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
+import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.random.JDKRandomGenerator;
import org.apache.commons.math.util.FastMath;
import org.junit.Test;
@@ -36,21 +37,22 @@ public class MultiStartUnivariateRealOptimizerTest {
public void testSinMin() throws MathException {
UnivariateRealFunction f = new SinFunction();
UnivariateRealOptimizer underlying = new BrentOptimizer();
+ underlying.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
+ underlying.setMaxEvaluations(300);
JDKRandomGenerator g = new JDKRandomGenerator();
g.setSeed(44428400075l);
- MultiStartUnivariateRealOptimizer minimizer =
+ MultiStartUnivariateRealOptimizer optimizer =
new MultiStartUnivariateRealOptimizer(underlying, 10, g);
- minimizer.optimize(f, GoalType.MINIMIZE, -100.0, 100.0);
- double[] optima = minimizer.getOptima();
- double[] optimaValues = minimizer.getOptimaValues();
+ optimizer.optimize(f, GoalType.MINIMIZE, -100.0, 100.0);
+ UnivariateRealPointValuePair[] optima = optimizer.getOptima();
for (int i = 1; i < optima.length; ++i) {
- double d = (optima[i] - optima[i-1]) / (2 * FastMath.PI);
+ double d = (optima[i].getPoint() - optima[i-1].getPoint()) / (2 * FastMath.PI);
assertTrue (FastMath.abs(d - FastMath.rint(d)) < 1.0e-8);
- assertEquals(-1.0, f.value(optima[i]), 1.0e-10);
- assertEquals(f.value(optima[i]), optimaValues[i], 1.0e-10);
+ assertEquals(-1.0, f.value(optima[i].getPoint()), 1.0e-10);
+ assertEquals(f.value(optima[i].getPoint()), optima[i].getValue(), 1.0e-10);
}
- assertTrue(minimizer.getEvaluations() > 150);
- assertTrue(minimizer.getEvaluations() < 250);
+ assertTrue(optimizer.getEvaluations() > 150);
+ assertTrue(optimizer.getEvaluations() < 250);
}
@Test
@@ -59,44 +61,23 @@ public class MultiStartUnivariateRealOptimizerTest {
// The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
UnivariateRealFunction f = new QuinticFunction();
UnivariateRealOptimizer underlying = new BrentOptimizer();
- underlying.setRelativeAccuracy(1e-15);
+ underlying.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-9, 1e-14));
+ underlying.setMaxEvaluations(300);
JDKRandomGenerator g = new JDKRandomGenerator();
g.setSeed(4312000053L);
- MultiStartUnivariateRealOptimizer minimizer =
+ MultiStartUnivariateRealOptimizer optimizer =
new MultiStartUnivariateRealOptimizer(underlying, 5, g);
- minimizer.setAbsoluteAccuracy(10 * minimizer.getAbsoluteAccuracy());
- minimizer.setRelativeAccuracy(10 * minimizer.getRelativeAccuracy());
- try {
- minimizer.getOptima();
- fail("an exception should have been thrown");
- } catch (IllegalStateException ise) {
- // expected
- } catch (Exception e) {
- fail("wrong exception caught");
- }
- try {
- minimizer.getOptimaValues();
- fail("an exception should have been thrown");
- } catch (IllegalStateException ise) {
- // expected
- } catch (Exception e) {
- fail("wrong exception caught");
- }
+ UnivariateRealPointValuePair optimum
+ = optimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2);
+ assertEquals(-0.2719561271, optimum.getPoint(), 1e-9);
+ assertEquals(-0.0443342695, optimum.getValue(), 1e-9);
- double result = minimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2);
- assertEquals(-0.2719561270319131, result, 1.0e-13);
- assertEquals(-0.2719561270319131, minimizer.getResult(), 1.0e-13);
- assertEquals(-0.04433426954946637, minimizer.getFunctionValue(), 1.0e-13);
-
- double[] optima = minimizer.getOptima();
- double[] optimaValues = minimizer.getOptimaValues();
+ UnivariateRealPointValuePair[] optima = optimizer.getOptima();
for (int i = 0; i < optima.length; ++i) {
- assertEquals(f.value(optima[i]), optimaValues[i], 1.0e-10);
+ assertEquals(f.value(optima[i].getPoint()), optima[i].getValue(), 1e-9);
}
- assertTrue(minimizer.getEvaluations() >= 120);
- assertTrue(minimizer.getEvaluations() <= 170);
- assertTrue(minimizer.getIterationCount() >= 120);
- assertTrue(minimizer.getIterationCount() <= 170);
+ assertTrue(optimizer.getEvaluations() >= 110);
+ assertTrue(optimizer.getEvaluations() <= 150);
}
}