MATH-397. Modified "AbstractUnivariateRealOptimizer" so that its usage is

more similar to what is done in package "optimization.general".
Deprecated many methods as a consequence of the new layout.
New utility methods in "ConvergingAlgorithmImpl".
Temporary workaround in "BrentOptimizer" (requirement from base class) to
avoid committing two issues at the same time...


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@980013 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2010-07-28 10:27:02 +00:00
parent c917b3b3fa
commit 7572385a7e
5 changed files with 182 additions and 20 deletions

View File

@ -17,7 +17,6 @@
package org.apache.commons.math; package org.apache.commons.math;
/** /**
* Provide a default implementation for several functions useful to generic * Provide a default implementation for several functions useful to generic
* converging algorithms. * converging algorithms.
@ -25,7 +24,7 @@ package org.apache.commons.math;
* @version $Revision$ $Date$ * @version $Revision$ $Date$
* @since 2.0 * @since 2.0
*/ */
public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm{ public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm {
/** Maximum absolute error. */ /** Maximum absolute error. */
protected double absoluteAccuracy; protected double absoluteAccuracy;
@ -45,7 +44,6 @@ public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm{
/** Default maximum number of iterations. */ /** Default maximum number of iterations. */
protected int defaultMaximalIterationCount; protected int defaultMaximalIterationCount;
// Mainly for test framework.
/** The last iteration count. */ /** The last iteration count. */
protected int iterationCount; protected int iterationCount;
@ -56,6 +54,8 @@ public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm{
* @param defaultMaximalIterationCount maximum number of iterations * @param defaultMaximalIterationCount maximum number of iterations
* @throws IllegalArgumentException if f is null or the * @throws IllegalArgumentException if f is null or the
* defaultAbsoluteAccuracy is not valid * defaultAbsoluteAccuracy is not valid
* @deprecated in 2.2. Derived classes should use the "setter" methods
* in order to assign meaningful values to all the instances variables.
*/ */
protected ConvergingAlgorithmImpl(final int defaultMaximalIterationCount, protected ConvergingAlgorithmImpl(final int defaultMaximalIterationCount,
final double defaultAbsoluteAccuracy) { final double defaultAbsoluteAccuracy) {
@ -68,6 +68,15 @@ public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm{
this.iterationCount = 0; this.iterationCount = 0;
} }
/**
* Default constructor.
*
* @since 2.2
* @deprecated in 2.2 (to be removed as soon as the single non-default one
* has been removed).
*/
protected ConvergingAlgorithmImpl() {}
/** {@inheritDoc} */ /** {@inheritDoc} */
public int getIterationCount() { public int getIterationCount() {
return iterationCount; return iterationCount;
@ -118,4 +127,26 @@ public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm{
relativeAccuracy = defaultRelativeAccuracy; relativeAccuracy = defaultRelativeAccuracy;
} }
/**
* Reset the iterations counter to 0.
*
* @since 2.2
*/
protected void resetIterationsCounter() {
iterationCount = 0;
}
/**
* Increment the iterations counter by 1.
*
* @throws OptimizationException if the maximal number
* of iterations is exceeded.
* @since 2.2
*/
protected void incrementIterationsCounter()
throws ConvergenceException {
if (++iterationCount > maximalIterationCount) {
throw new ConvergenceException(new MaxIterationsExceededException(maximalIterationCount));
}
}
} }

View File

@ -19,11 +19,13 @@ package org.apache.commons.math.optimization.univariate;
import org.apache.commons.math.ConvergingAlgorithmImpl; import org.apache.commons.math.ConvergingAlgorithmImpl;
import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.MaxEvaluationsExceededException; import org.apache.commons.math.MaxEvaluationsExceededException;
import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.exception.NotStrictlyPositiveException;
import org.apache.commons.math.exception.NoDataException;
import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.optimization.UnivariateRealOptimizer; import org.apache.commons.math.optimization.UnivariateRealOptimizer;
import org.apache.commons.math.util.LocalizedFormats; import org.apache.commons.math.optimization.GoalType;
/** /**
* Provide a default implementation for several functions useful to generic * Provide a default implementation for several functions useful to generic
@ -34,21 +36,26 @@ import org.apache.commons.math.util.LocalizedFormats;
*/ */
public abstract class AbstractUnivariateRealOptimizer public abstract class AbstractUnivariateRealOptimizer
extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer { extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer {
/** Indicates where a root has been computed. */ /** Indicates where a root has been computed. */
protected boolean resultComputed; private boolean resultComputed;
/** The last computed root. */ /** The last computed root. */
protected double result; private double result;
/** Value of the function at the last computed result. */ /** Value of the function at the last computed result. */
protected double functionValue; private double functionValue;
/** Maximal number of evaluations allowed. */ /** Maximal number of evaluations allowed. */
private int maxEvaluations; private int maxEvaluations;
/** Number of evaluations already performed. */ /** Number of evaluations already performed. */
private int evaluations; private int evaluations;
/** Optimization type */
private GoalType goal;
/** Lower end of search interval. */
private double min;
/** Higher end of search interval. */
private double max;
/** Initial guess . */
private double startValue;
/** Function to optimize. */
private UnivariateRealFunction function;
/** /**
* Construct a solver with given iteration count and accuracy. * Construct a solver with given iteration count and accuracy.
@ -57,6 +64,9 @@ public abstract class AbstractUnivariateRealOptimizer
* @param defaultMaximalIterationCount maximum number of iterations * @param defaultMaximalIterationCount maximum number of iterations
* @throws IllegalArgumentException if f is null or the * @throws IllegalArgumentException if f is null or the
* defaultAbsoluteAccuracy is not valid * 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, protected AbstractUnivariateRealOptimizer(final int defaultMaximalIterationCount,
final double defaultAbsoluteAccuracy) { final double defaultAbsoluteAccuracy) {
@ -65,24 +75,41 @@ public abstract class AbstractUnivariateRealOptimizer
setMaxEvaluations(Integer.MAX_VALUE); setMaxEvaluations(Integer.MAX_VALUE);
} }
/** Check if a result has been computed. /**
* @exception IllegalStateException if no result has been computed * Default constructor.
* To be removed once the single non-default one has been removed.
*/ */
protected void checkResultComputed() throws IllegalStateException { 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) { if (!resultComputed) {
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_RESULT_AVAILABLE); throw new NoDataException();
} }
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public double getResult() { public double getResult() {
checkResultComputed(); if (!resultComputed) {
throw new NoDataException();
}
return result; return result;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public double getFunctionValue() { public double getFunctionValue() {
checkResultComputed(); if (functionValue == Double.NaN) {
final double opt = getResult();
try {
functionValue = function.value(opt);
} catch (FunctionEvaluationException e) {
throw new RuntimeException(e);
}
}
return functionValue; return functionValue;
} }
@ -92,6 +119,7 @@ public abstract class AbstractUnivariateRealOptimizer
* @param x the result to set * @param x the result to set
* @param fx the result to set * @param fx the result to set
* @param iterationCount the iteration count 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, protected final void setResult(final double x, final double fx,
final int iterationCount) { final int iterationCount) {
@ -103,6 +131,7 @@ public abstract class AbstractUnivariateRealOptimizer
/** /**
* Convenience function for implementations. * Convenience function for implementations.
* @deprecated in 2.2 (no alternative).
*/ */
protected final void clearResult() { protected final void clearResult() {
this.resultComputed = false; this.resultComputed = false;
@ -123,6 +152,31 @@ public abstract class AbstractUnivariateRealOptimizer
return evaluations; return evaluations;
} }
/**
* @return the optimization type.
*/
public GoalType getGoalType() {
return goal;
}
/**
* @return the lower of the search interval.
*/
public double getMin() {
return min;
}
/**
* @return the higher of the search interval.
*/
public double getMax() {
return max;
}
/**
* @return the initial guess.
*/
public double getStartValue() {
return startValue;
}
/** /**
* Compute the objective function value. * Compute the objective function value.
* @param f objective function * @param f objective function
@ -130,6 +184,8 @@ public abstract class AbstractUnivariateRealOptimizer
* @return objective function value at specified point * @return objective function value at specified point
* @exception FunctionEvaluationException if the function cannot be evaluated * @exception FunctionEvaluationException if the function cannot be evaluated
* or the maximal number of iterations is exceeded * 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, protected double computeObjectiveValue(final UnivariateRealFunction f,
final double point) final double point)
@ -141,4 +197,68 @@ public abstract class AbstractUnivariateRealOptimizer
return f.value(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.
*/
protected double computeObjectiveValue(double point)
throws FunctionEvaluationException {
if (++evaluations > maxEvaluations) {
resultComputed = false;
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
point);
}
return function.value(point);
}
/** {@inheritDoc} */
public double optimize(UnivariateRealFunction function, GoalType goal,
double min, double max, double startValue)
throws MaxIterationsExceededException, FunctionEvaluationException {
// Initialize.
this.min = min;
this.max = max;
this.startValue = startValue;
this.goal = goal;
this.function = function;
// Reset.
functionValue = Double.NaN;
evaluations = 0;
resetIterationsCounter();
// 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;
}
/** {@inheritDoc} */
public double optimize(UnivariateRealFunction f, GoalType goal,
double min, double max)
throws MaxIterationsExceededException, FunctionEvaluationException {
return optimize(f, goal, min, max, min + 0.5 * (max - min));
}
/**
* Method for implementing actual optimization algorithms in derived
* classes.
*
* @return the optimum.
*/
protected abstract double doOptimize();
} }

View File

@ -236,4 +236,9 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
} }
throw new MaxIterationsExceededException(maximalIterationCount); throw new MaxIterationsExceededException(maximalIterationCount);
} }
/** Temporary workaround. */
protected double doOptimize() {
throw new UnsupportedOperationException();
}
} }

View File

@ -52,6 +52,11 @@ The <action> type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces! If the output is not quite correct, check for invisible trailing spaces!
--> -->
<release version="2.2" date="TBD" description="TBD"> <release version="2.2" date="TBD" description="TBD">
<action dev="erans" type="update" issue="MATH-397">
Modified "AbstractUnivariateRealOptimizer" to make it more similar to
"BaseAbstractScalarOptimizer".
Added utility methods in "ConvergingAlgorithmImpl".
</action>
<action dev="erans" type="fix" issue="MATH-395"> <action dev="erans" type="fix" issue="MATH-395">
Fixed several bugs in "BrentOptimizer". Fixed several bugs in "BrentOptimizer".
</action> </action>

View File

@ -23,6 +23,7 @@ import static org.junit.Assert.fail;
import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathException; import org.apache.commons.math.MathException;
import org.apache.commons.math.MaxIterationsExceededException; import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.exception.NoDataException;
import org.apache.commons.math.analysis.QuinticFunction; import org.apache.commons.math.analysis.QuinticFunction;
import org.apache.commons.math.analysis.SinFunction; import org.apache.commons.math.analysis.SinFunction;
import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.UnivariateRealFunction;
@ -44,7 +45,7 @@ public final class BrentOptimizerTest {
try { try {
minimizer.getResult(); minimizer.getResult();
fail("an exception should have been thrown"); fail("an exception should have been thrown");
} catch (IllegalStateException ise) { } catch (NoDataException ise) {
// expected // expected
} catch (Exception e) { } catch (Exception e) {
fail("wrong exception caught"); fail("wrong exception caught");