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    }