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 }