/* * 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.ConvergingAlgorithmImpl; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.MaxEvaluationsExceededException; import org.apache.commons.math.MaxIterationsExceededException; import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.exception.MathUnsupportedOperationException; import org.apache.commons.math.exception.NoDataException; import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.optimization.GoalType; import org.apache.commons.math.optimization.UnivariateRealOptimizer; /** * Provide a default implementation for several functions useful to generic * optimizers. * * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 févr. 2011) $ * @since 2.0 */ public abstract class AbstractUnivariateRealOptimizer extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer { /** Indicates where a root has been computed. */ protected boolean resultComputed; /** The last computed root. */ protected double result; /** Value of the function at the last computed result. */ protected double functionValue; /** Maximal number of evaluations allowed. */ private int maxEvaluations; /** Number of evaluations already performed. */ private int evaluations; /** Optimization type */ private GoalType optimizationGoal; /** Lower end of search interval. */ private double searchMin; /** Higher end of search interval. */ private double searchMax; /** Initial guess . */ private double searchStart; /** Function to optimize. */ private UnivariateRealFunction function; /** * Construct a solver with given iteration count and accuracy. * @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. */ @Deprecated 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). */ @Deprecated protected void checkResultComputed() { if (!resultComputed) { throw new NoDataException(); } } /** {@inheritDoc} */ public double getResult() { if (!resultComputed) { throw new NoDataException(); } return result; } /** {@inheritDoc} */ public double getFunctionValue() throws FunctionEvaluationException { if (Double.isNaN(functionValue)) { final double opt = getResult(); functionValue = function.value(opt); } 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). */ @Deprecated 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). */ @Deprecated protected final void clearResult() { this.resultComputed = false; } /** {@inheritDoc} */ public void setMaxEvaluations(int maxEvaluations) { this.maxEvaluations = maxEvaluations; } /** {@inheritDoc} */ public int getMaxEvaluations() { return maxEvaluations; } /** {@inheritDoc} */ public int getEvaluations() { return evaluations; } /** * @return the optimization type. */ public GoalType getGoalType() { return optimizationGoal; } /** * @return the lower of the search interval. */ public double getMin() { return searchMin; } /** * @return the higher of the search interval. */ public double getMax() { return searchMax; } /** * @return the initial guess. */ public double getStartValue() { 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. */ @Deprecated 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. */ 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 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; // 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. * * From version 3.0 onwards, this method will be abstract - i.e. * concrete implementations will have to implement it. If this method * is not implemented, subclasses must override * {@link #optimize(UnivariateRealFunction, GoalType, double, double)}. * * @return the optimum. * @throws MaxIterationsExceededException if the maximum iteration count * is exceeded. * @throws FunctionEvaluationException if an error occurs evaluating * the function. */ protected double doOptimize() throws MaxIterationsExceededException, FunctionEvaluationException { throw new MathUnsupportedOperationException(LocalizedFormats.NOT_OVERRIDEN); } }