    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.math.optimization.univariate;
    019
    020    import org.apache.commons.math.ConvergingAlgorithmImpl;
    021    import org.apache.commons.math.FunctionEvaluationException;
    022    import org.apache.commons.math.MaxEvaluationsExceededException;
    023    import org.apache.commons.math.MaxIterationsExceededException;
    024    import org.apache.commons.math.analysis.UnivariateRealFunction;
    025    import org.apache.commons.math.exception.MathUnsupportedOperationException;
    026    import org.apache.commons.math.exception.NoDataException;
    027    import org.apache.commons.math.exception.util.LocalizedFormats;
    028    import org.apache.commons.math.optimization.GoalType;
    029    import org.apache.commons.math.optimization.UnivariateRealOptimizer;
    030
    031    /**
    032     * Provide a default implementation for several functions useful to generic
    033     * optimizers.
    034     *
    035     * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 f??vr. 2011) $
    036     * @since 2.0
    037     */
    038    public abstract class AbstractUnivariateRealOptimizer
    039        extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer {
    040        /** Indicates where a root has been computed. */
    041        protected boolean resultComputed;
    042        /** The last computed root. */
    043        protected double result;
    044        /** Value of the function at the last computed result. */
    045        protected double functionValue;
    046        /** Maximal number of evaluations allowed. */
    047        private int maxEvaluations;
    048        /** Number of evaluations already performed. */
    049        private int evaluations;
    050        /** Optimization type */
    051        private GoalType optimizationGoal;
    052        /** Lower end of search interval. */
    053        private double searchMin;
    054        /** Higher end of search interval. */
    055        private double searchMax;
    056        /** Initial guess . */
    057        private double searchStart;
    058        /** Function to optimize. */
    059        private UnivariateRealFunction function;
    060
    061        /**
    062         * Construct a solver with given iteration count and accuracy.
    063         * @param defaultAbsoluteAccuracy maximum absolute error
    064         * @param defaultMaximalIterationCount maximum number of iterations
    065         * @throws IllegalArgumentException if f is null or the
    066         * defaultAbsoluteAccuracy is not valid
    067         * @deprecated in 2.2. Please use the "setter" methods to assign meaningful
    068         * values to the maximum numbers of iterations and evaluations, and to the
    069         * absolute and relative accuracy thresholds.
    070         */
    071        @Deprecated
    072        protected AbstractUnivariateRealOptimizer(final int defaultMaximalIterationCount,
    073                                                  final double defaultAbsoluteAccuracy) {
    074            super(defaultMaximalIterationCount, defaultAbsoluteAccuracy);
    075            resultComputed = false;
    076            setMaxEvaluations(Integer.MAX_VALUE);
    077        }
    078
    079        /**
    080         * Default constructor.
    081         * To be removed once the single non-default one has been removed.
    082         */
    083        protected AbstractUnivariateRealOptimizer() {}
    084
    085        /**
    086         * Check whether a result has been computed.
    087         * @throws NoDataException if no result has been computed
    088         * @deprecated in 2.2 (no alternative).
    089         */
    090        @Deprecated
    091        protected void checkResultComputed() {
    092            if (!resultComputed) {
    093                throw new NoDataException();
    094            }
    095        }
    096
    097        /** {@inheritDoc} */
    098        public double getResult() {
    099            if (!resultComputed) {
    100                throw new NoDataException();
    101            }
    102            return result;
    103        }
    104
    105        /** {@inheritDoc} */
    106        public double getFunctionValue() throws FunctionEvaluationException {
    107            if (Double.isNaN(functionValue)) {
    108                final double opt = getResult();
    109                functionValue = function.value(opt);
    110            }
    111            return functionValue;
    112        }
    113
    114        /**
    115         * Convenience function for implementations.
    116         *
    117         * @param x the result to set
    118         * @param fx the result to set
    119         * @param iterationCount the iteration count to set
    120         * @deprecated in 2.2 (no alternative).
    121         */
    122        @Deprecated
    123        protected final void setResult(final double x, final double fx,
    124                                       final int iterationCount) {
    125            this.result         = x;
    126            this.functionValue  = fx;
    127            this.iterationCount = iterationCount;
    128            this.resultComputed = true;
    129        }
    130
    131        /**
    132         * Convenience function for implementations.
    133         * @deprecated in 2.2 (no alternative).
    134         */
    135        @Deprecated
    136        protected final void clearResult() {
    137            this.resultComputed = false;
    138        }
    139
    140        /** {@inheritDoc} */
    141        public void setMaxEvaluations(int maxEvaluations) {
    142            this.maxEvaluations = maxEvaluations;
    143        }
    144
    145        /** {@inheritDoc} */
    146        public int getMaxEvaluations() {
    147            return maxEvaluations;
    148        }
    149
    150        /** {@inheritDoc} */
    151        public int getEvaluations() {
    152            return evaluations;
    153        }
    154
    155        /**
    156         * @return the optimization type.
    157         */
    158        public GoalType getGoalType() {
    159            return optimizationGoal;
    160        }
    161        /**
    162         * @return the lower of the search interval.
    163         */
    164        public double getMin() {
    165            return searchMin;
    166        }
    167        /**
    168         * @return the higher of the search interval.
    169         */
    170        public double getMax() {
    171            return searchMax;
    172        }
    173        /**
    174         * @return the initial guess.
    175         */
    176        public double getStartValue() {
    177            return searchStart;
    178        }
    179
    180        /**
    181         * Compute the objective function value.
    182         * @param f objective function
    183         * @param point point at which the objective function must be evaluated
    184         * @return objective function value at specified point
    185         * @exception FunctionEvaluationException if the function cannot be evaluated
    186         * or the maximal number of iterations is exceeded
    187         * @deprecated in 2.2. Use this {@link #computeObjectiveValue(double)
    188         * replacement} instead.
    189         */
    190        @Deprecated
    191        protected double computeObjectiveValue(final UnivariateRealFunction f,
    192                                               final double point)
    193            throws FunctionEvaluationException {
    194            if (++evaluations > maxEvaluations) {
    195                throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations), point);
    196            }
    197            return f.value(point);
    198        }
    199
    200        /**
    201         * Compute the objective function value.
    202         *
    203         * @param point Point at which the objective function must be evaluated.
    204         * @return the objective function value at specified point.
    205         * @exception FunctionEvaluationException if the function cannot be evaluated
    206         * or the maximal number of iterations is exceeded.
    207         */
    208        protected double computeObjectiveValue(double point)
    209            throws FunctionEvaluationException {
    210            if (++evaluations > maxEvaluations) {
    211                resultComputed = false;
    212                throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations), point);
    213            }
    214            return function.value(point);
    215        }
    216
    217        /** {@inheritDoc} */
    218        public double optimize(UnivariateRealFunction f, GoalType goal,
    219                               double min, double max, double startValue)
    220            throws MaxIterationsExceededException, FunctionEvaluationException {
    221            // Initialize.
    222            this.searchMin = min;
    223            this.searchMax = max;
    224            this.searchStart = startValue;
    225            this.optimizationGoal = goal;
    226            this.function = f;
    227
    228            // Reset.
    229            functionValue = Double.NaN;
    230            evaluations = 0;
    231            resetIterationsCounter();
    232
    233            // Perform computation.
    234            result = doOptimize();
    235            resultComputed = true;
    236
    237            return result;
    238        }
    239
    240        /**
    241         * Set the value at the optimum.
    242         *
    243         * @param functionValue Value of the objective function at the optimum.
    244         */
    245        protected void setFunctionValue(double functionValue) {
    246            this.functionValue = functionValue;
    247        }
    248
    249        /** {@inheritDoc} */
    250        public double optimize(UnivariateRealFunction f, GoalType goal,
    251                               double min, double max)
    252            throws MaxIterationsExceededException, FunctionEvaluationException {
    253            return optimize(f, goal, min, max, min + 0.5 * (max - min));
    254        }
    255
    256        /**
    257         * Method for implementing actual optimization algorithms in derived
    258         * classes.
    259         *
    260         * From version 3.0 onwards, this method will be abstract - i.e.
    261         * concrete implementations will have to implement it.  If this method
    262         * is not implemented, subclasses must override
    263         * {@link #optimize(UnivariateRealFunction, GoalType, double, double)}.
    264         *
    265         * @return the optimum.
    266         * @throws MaxIterationsExceededException if the maximum iteration count
    267         * is exceeded.
    268         * @throws FunctionEvaluationException if an error occurs evaluating
    269         * the function.
    270         */
    271        protected double doOptimize()
    272            throws MaxIterationsExceededException, FunctionEvaluationException {
    273            throw new MathUnsupportedOperationException(LocalizedFormats.NOT_OVERRIDEN);
    274        }
    275    }