Raymond | dee0849 | 2015-04-02 10:43:13 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more |
| 3 | * contributor license agreements. See the NOTICE file distributed with |
| 4 | * this work for additional information regarding copyright ownership. |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
| 6 | * (the "License"); you may not use this file except in compliance with |
| 7 | * the License. You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
| 18 | package org.apache.commons.math.optimization.univariate; |
| 19 | |
| 20 | import org.apache.commons.math.ConvergingAlgorithmImpl; |
| 21 | import org.apache.commons.math.FunctionEvaluationException; |
| 22 | import org.apache.commons.math.MaxEvaluationsExceededException; |
| 23 | import org.apache.commons.math.MaxIterationsExceededException; |
| 24 | import org.apache.commons.math.analysis.UnivariateRealFunction; |
| 25 | import org.apache.commons.math.exception.MathUnsupportedOperationException; |
| 26 | import org.apache.commons.math.exception.NoDataException; |
| 27 | import org.apache.commons.math.exception.util.LocalizedFormats; |
| 28 | import org.apache.commons.math.optimization.GoalType; |
| 29 | import org.apache.commons.math.optimization.UnivariateRealOptimizer; |
| 30 | |
| 31 | /** |
| 32 | * Provide a default implementation for several functions useful to generic |
| 33 | * optimizers. |
| 34 | * |
| 35 | * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 févr. 2011) $ |
| 36 | * @since 2.0 |
| 37 | */ |
| 38 | public abstract class AbstractUnivariateRealOptimizer |
| 39 | extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer { |
| 40 | /** Indicates where a root has been computed. */ |
| 41 | protected boolean resultComputed; |
| 42 | /** The last computed root. */ |
| 43 | protected double result; |
| 44 | /** Value of the function at the last computed result. */ |
| 45 | protected double functionValue; |
| 46 | /** Maximal number of evaluations allowed. */ |
| 47 | private int maxEvaluations; |
| 48 | /** Number of evaluations already performed. */ |
| 49 | private int evaluations; |
| 50 | /** Optimization type */ |
| 51 | private GoalType optimizationGoal; |
| 52 | /** Lower end of search interval. */ |
| 53 | private double searchMin; |
| 54 | /** Higher end of search interval. */ |
| 55 | private double searchMax; |
| 56 | /** Initial guess . */ |
| 57 | private double searchStart; |
| 58 | /** Function to optimize. */ |
| 59 | private UnivariateRealFunction function; |
| 60 | |
| 61 | /** |
| 62 | * Construct a solver with given iteration count and accuracy. |
| 63 | * @param defaultAbsoluteAccuracy maximum absolute error |
| 64 | * @param defaultMaximalIterationCount maximum number of iterations |
| 65 | * @throws IllegalArgumentException if f is null or the |
| 66 | * defaultAbsoluteAccuracy is not valid |
| 67 | * @deprecated in 2.2. Please use the "setter" methods to assign meaningful |
| 68 | * values to the maximum numbers of iterations and evaluations, and to the |
| 69 | * absolute and relative accuracy thresholds. |
| 70 | */ |
| 71 | @Deprecated |
| 72 | protected AbstractUnivariateRealOptimizer(final int defaultMaximalIterationCount, |
| 73 | final double defaultAbsoluteAccuracy) { |
| 74 | super(defaultMaximalIterationCount, defaultAbsoluteAccuracy); |
| 75 | resultComputed = false; |
| 76 | setMaxEvaluations(Integer.MAX_VALUE); |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * Default constructor. |
| 81 | * To be removed once the single non-default one has been removed. |
| 82 | */ |
| 83 | protected AbstractUnivariateRealOptimizer() {} |
| 84 | |
| 85 | /** |
| 86 | * Check whether a result has been computed. |
| 87 | * @throws NoDataException if no result has been computed |
| 88 | * @deprecated in 2.2 (no alternative). |
| 89 | */ |
| 90 | @Deprecated |
| 91 | protected void checkResultComputed() { |
| 92 | if (!resultComputed) { |
| 93 | throw new NoDataException(); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | /** {@inheritDoc} */ |
| 98 | public double getResult() { |
| 99 | 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 | } |