Implemented proposed solution (rethrow last exception if no optimum were found).


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1035245 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2010-11-15 12:22:47 +00:00
parent 65e95d0224
commit 0d52bf6394
3 changed files with 47 additions and 30 deletions

View File

@ -20,7 +20,7 @@ package org.apache.commons.math.optimization;
import java.util.Arrays;
import java.util.Comparator;
import org.apache.commons.math.exception.FunctionEvaluationException;
import org.apache.commons.math.exception.MathUserException;
import org.apache.commons.math.exception.MathIllegalStateException;
import org.apache.commons.math.exception.ConvergenceException;
import org.apache.commons.math.analysis.MultivariateRealFunction;
@ -89,13 +89,14 @@ public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRe
* descending order if maximizing), followed by and null elements
* corresponding to the runs that did not converge. This means all
* elements will be null if the {@link #optimize(MultivariateRealFunction,GoalType,double[])
* optimize} method did throw a {@link ConvergenceException}).
* optimize} method did throw a {@link MathUserException}).
* 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(MultivariateRealFunction,GoalType,double[]) optimize} has not been called.
* #optimize(MultivariateRealFunction,GoalType,double[]) optimize}
* has not been called.
*/
public RealPointValuePair[] getOptima() {
if (optima == null) {
@ -135,19 +136,18 @@ public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRe
*/
public RealPointValuePair optimize(final FUNC f,
final GoalType goal,
double[] startPoint)
throws FunctionEvaluationException {
double[] startPoint) {
MathUserException lastException = null;
optima = new RealPointValuePair[starts];
totalEvaluations = 0;
// Multi-start loop.
for (int i = 0; i < starts; ++i) {
try {
optima[i] = optimizer.optimize(f, goal,
i == 0 ? startPoint : generator.nextVector());
} catch (FunctionEvaluationException fee) {
optima[i] = null;
} catch (ConvergenceException oe) {
} catch (MathUserException mue) {
lastException = mue;
optima[i] = null;
}
@ -159,8 +159,7 @@ public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRe
sortPairs(goal);
if (optima[0] == null) {
throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
starts);
throw lastException;
}
// Return the found point given the best objective function value.

View File

@ -20,10 +20,9 @@ package org.apache.commons.math.optimization.univariate;
import java.util.Arrays;
import java.util.Comparator;
import org.apache.commons.math.exception.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.exception.MathUserException;
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;
@ -121,14 +120,15 @@ public class MultiStartUnivariateRealOptimizer<FUNC extends UnivariateRealFuncti
* 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(UnivariateRealFunction,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.
* #optimize(UnivariateRealFunction,GoalType,double,double) optimize}
* method did throw a {@link MathUserException}). 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(UnivariateRealFunction,GoalType,double,double) optimize} has not been called.
* #optimize(UnivariateRealFunction,GoalType,double,double) optimize}
* has not been called.
*/
public UnivariateRealPointValuePair[] getOptima() {
if (optima == null) {
@ -140,16 +140,15 @@ public class MultiStartUnivariateRealOptimizer<FUNC extends UnivariateRealFuncti
/** {@inheritDoc} */
public UnivariateRealPointValuePair optimize(final FUNC f,
final GoalType goal,
final double min, final double max)
throws FunctionEvaluationException {
final double min, final double max) {
return optimize(f, goal, min, max, min + 0.5 * (max - min));
}
/** {@inheritDoc} */
public UnivariateRealPointValuePair optimize(final FUNC f, final GoalType goal,
final double min, final double max,
final double startValue)
throws FunctionEvaluationException {
final double startValue) {
MathUserException lastException = null;
optima = new UnivariateRealPointValuePair[starts];
totalEvaluations = 0;
@ -158,9 +157,8 @@ public class MultiStartUnivariateRealOptimizer<FUNC extends UnivariateRealFuncti
try {
final double s = (i == 0) ? startValue : min + generator.nextDouble() * (max - min);
optima[i] = optimizer.optimize(f, goal, min, max, s);
} catch (FunctionEvaluationException fee) {
optima[i] = null;
} catch (ConvergenceException ce) {
} catch (MathUserException mue) {
lastException = mue;
optima[i] = null;
}
@ -172,8 +170,7 @@ public class MultiStartUnivariateRealOptimizer<FUNC extends UnivariateRealFuncti
sortPairs(goal);
if (optima[0] == null) {
throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
starts);
throw lastException;
}
// Return the point with the best objective function value.

View File

@ -19,7 +19,7 @@ package org.apache.commons.math.optimization.univariate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.apache.commons.math.MathException;
import org.apache.commons.math.exception.MathUserException;
import org.apache.commons.math.analysis.QuinticFunction;
import org.apache.commons.math.analysis.SinFunction;
import org.apache.commons.math.analysis.UnivariateRealFunction;
@ -32,7 +32,7 @@ import org.junit.Test;
public class MultiStartUnivariateRealOptimizerTest {
@Test
public void testSinMin() throws MathException {
public void testSinMin() {
UnivariateRealFunction f = new SinFunction();
UnivariateRealOptimizer underlying = new BrentOptimizer(1e-10, 1e-14);
underlying.setMaxEvaluations(300);
@ -53,7 +53,7 @@ public class MultiStartUnivariateRealOptimizerTest {
}
@Test
public void testQuinticMin() throws MathException {
public void testQuinticMin() {
// The quintic function has zeros at 0, +-0.5 and +-1.
// The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
UnivariateRealFunction f = new QuinticFunction();
@ -76,4 +76,25 @@ public class MultiStartUnivariateRealOptimizerTest {
assertTrue(optimizer.getEvaluations() >= 50);
assertTrue(optimizer.getEvaluations() <= 100);
}
@Test(expected=MathUserException.class)
public void testBadFunction() {
UnivariateRealFunction f = new UnivariateRealFunction() {
public double value(double x) {
if (x < 0) {
throw new MathUserException();
}
return 0;
}
};
UnivariateRealOptimizer underlying = new BrentOptimizer(1e-9, 1e-14);
underlying.setMaxEvaluations(300);
JDKRandomGenerator g = new JDKRandomGenerator();
g.setSeed(4312000053L);
MultiStartUnivariateRealOptimizer<UnivariateRealFunction> optimizer =
new MultiStartUnivariateRealOptimizer<UnivariateRealFunction>(underlying, 5, g);
UnivariateRealPointValuePair optimum
= optimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2);
}
}