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:
parent
c917b3b3fa
commit
7572385a7e
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in New Issue