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 18package org.apache.commons.math.analysis.solvers; 19 20import org.apache.commons.math.ConvergingAlgorithmImpl; 21import org.apache.commons.math.FunctionEvaluationException; 22import org.apache.commons.math.MathRuntimeException; 23import org.apache.commons.math.analysis.UnivariateRealFunction; 24import org.apache.commons.math.exception.util.LocalizedFormats; 25import org.apache.commons.math.ConvergenceException; 26import org.apache.commons.math.exception.NullArgumentException; 27 28/** 29 * Provide a default implementation for several functions useful to generic 30 * solvers. 31 * 32 * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 févr. 2011) $ 33 * @deprecated in 2.2 (to be removed in 3.0). 34 */ 35@Deprecated 36public abstract class UnivariateRealSolverImpl 37 extends ConvergingAlgorithmImpl implements UnivariateRealSolver { 38 39 /** Maximum error of function. */ 40 protected double functionValueAccuracy; 41 42 /** Default maximum error of function. */ 43 protected double defaultFunctionValueAccuracy; 44 45 /** Indicates where a root has been computed. */ 46 protected boolean resultComputed = false; 47 48 /** The last computed root. */ 49 protected double result; 50 51 /** Value of the function at the last computed result. */ 52 protected double functionValue; 53 54 /** The function to solve. 55 * @deprecated as of 2.0 the function to solve is passed as an argument 56 * to the {@link #solve(UnivariateRealFunction, double, double)} or 57 * {@link UnivariateRealSolverImpl#solve(UnivariateRealFunction, double, double, double)} 58 * method. */ 59 @Deprecated 60 protected UnivariateRealFunction f; 61 62 /** 63 * Construct a solver with given iteration count and accuracy. 64 * 65 * @param f the function to solve. 66 * @param defaultAbsoluteAccuracy maximum absolute error 67 * @param defaultMaximalIterationCount maximum number of iterations 68 * @throws IllegalArgumentException if f is null or the 69 * defaultAbsoluteAccuracy is not valid 70 * @deprecated as of 2.0 the function to solve is passed as an argument 71 * to the {@link #solve(UnivariateRealFunction, double, double)} or 72 * {@link UnivariateRealSolverImpl#solve(UnivariateRealFunction, double, double, double)} 73 * method. 74 */ 75 @Deprecated 76 protected UnivariateRealSolverImpl(final UnivariateRealFunction f, 77 final int defaultMaximalIterationCount, 78 final double defaultAbsoluteAccuracy) { 79 super(defaultMaximalIterationCount, defaultAbsoluteAccuracy); 80 if (f == null) { 81 throw new NullArgumentException(LocalizedFormats.FUNCTION); 82 } 83 this.f = f; 84 this.defaultFunctionValueAccuracy = 1.0e-15; 85 this.functionValueAccuracy = defaultFunctionValueAccuracy; 86 } 87 88 /** 89 * Construct a solver with given iteration count and accuracy. 90 * 91 * @param defaultAbsoluteAccuracy maximum absolute error 92 * @param defaultMaximalIterationCount maximum number of iterations 93 * @throws IllegalArgumentException if f is null or the 94 * defaultAbsoluteAccuracy is not valid 95 */ 96 protected UnivariateRealSolverImpl(final int defaultMaximalIterationCount, 97 final double defaultAbsoluteAccuracy) { 98 super(defaultMaximalIterationCount, defaultAbsoluteAccuracy); 99 this.defaultFunctionValueAccuracy = 1.0e-15; 100 this.functionValueAccuracy = defaultFunctionValueAccuracy; 101 } 102 103 /** Check if a result has been computed. 104 * @exception IllegalStateException if no result has been computed 105 */ 106 protected void checkResultComputed() throws IllegalStateException { 107 if (!resultComputed) { 108 throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_RESULT_AVAILABLE); 109 } 110 } 111 112 /** {@inheritDoc} */ 113 public double getResult() { 114 checkResultComputed(); 115 return result; 116 } 117 118 /** {@inheritDoc} */ 119 public double getFunctionValue() { 120 checkResultComputed(); 121 return functionValue; 122 } 123 124 /** {@inheritDoc} */ 125 public void setFunctionValueAccuracy(final double accuracy) { 126 functionValueAccuracy = accuracy; 127 } 128 129 /** {@inheritDoc} */ 130 public double getFunctionValueAccuracy() { 131 return functionValueAccuracy; 132 } 133 134 /** {@inheritDoc} */ 135 public void resetFunctionValueAccuracy() { 136 functionValueAccuracy = defaultFunctionValueAccuracy; 137 } 138 139 /** 140 * Solve for a zero root in the given interval. 141 * <p>A solver may require that the interval brackets a single zero root. 142 * Solvers that do require bracketing should be able to handle the case 143 * where one of the endpoints is itself a root.</p> 144 * 145 * @param function the function to solve. 146 * @param min the lower bound for the interval. 147 * @param max the upper bound for the interval. 148 * @param maxEval Maximum number of evaluations. 149 * @return a value where the function is zero 150 * @throws ConvergenceException if the maximum iteration count is exceeded 151 * or the solver detects convergence problems otherwise. 152 * @throws FunctionEvaluationException if an error occurs evaluating the function 153 * @throws IllegalArgumentException if min > max or the endpoints do not 154 * satisfy the requirements specified by the solver 155 * @since 2.2 156 */ 157 public double solve(int maxEval, UnivariateRealFunction function, double min, double max) 158 throws ConvergenceException, FunctionEvaluationException { 159 throw MathRuntimeException.createUnsupportedOperationException(LocalizedFormats.NOT_OVERRIDEN); 160 } 161 162 /** 163 * Solve for a zero in the given interval, start at startValue. 164 * <p>A solver may require that the interval brackets a single zero root. 165 * Solvers that do require bracketing should be able to handle the case 166 * where one of the endpoints is itself a root.</p> 167 * 168 * @param function the function to solve. 169 * @param min the lower bound for the interval. 170 * @param max the upper bound for the interval. 171 * @param startValue the start value to use 172 * @param maxEval Maximum number of evaluations. 173 * @return a value where the function is zero 174 * @throws ConvergenceException if the maximum iteration count is exceeded 175 * or the solver detects convergence problems otherwise. 176 * @throws FunctionEvaluationException if an error occurs evaluating the function 177 * @throws IllegalArgumentException if min > max or the arguments do not 178 * satisfy the requirements specified by the solver 179 * @since 2.2 180 */ 181 public double solve(int maxEval, UnivariateRealFunction function, double min, double max, double startValue) 182 throws ConvergenceException, FunctionEvaluationException, IllegalArgumentException { 183 throw MathRuntimeException.createUnsupportedOperationException(LocalizedFormats.NOT_OVERRIDEN); 184 } 185 186 /** 187 * Convenience function for implementations. 188 * 189 * @param newResult the result to set 190 * @param iterationCount the iteration count to set 191 */ 192 protected final void setResult(final double newResult, final int iterationCount) { 193 this.result = newResult; 194 this.iterationCount = iterationCount; 195 this.resultComputed = true; 196 } 197 198 /** 199 * Convenience function for implementations. 200 * 201 * @param x the result to set 202 * @param fx the result to set 203 * @param iterationCount the iteration count to set 204 */ 205 protected final void setResult(final double x, final double fx, 206 final int iterationCount) { 207 this.result = x; 208 this.functionValue = fx; 209 this.iterationCount = iterationCount; 210 this.resultComputed = true; 211 } 212 213 /** 214 * Convenience function for implementations. 215 */ 216 protected final void clearResult() { 217 this.iterationCount = 0; 218 this.resultComputed = false; 219 } 220 221 /** 222 * Returns true iff the function takes opposite signs at the endpoints. 223 * 224 * @param lower the lower endpoint 225 * @param upper the upper endpoint 226 * @param function the function 227 * @return true if f(lower) * f(upper) < 0 228 * @throws FunctionEvaluationException if an error occurs evaluating the function at the endpoints 229 */ 230 protected boolean isBracketing(final double lower, final double upper, 231 final UnivariateRealFunction function) 232 throws FunctionEvaluationException { 233 final double f1 = function.value(lower); 234 final double f2 = function.value(upper); 235 return (f1 > 0 && f2 < 0) || (f1 < 0 && f2 > 0); 236 } 237 238 /** 239 * Returns true if the arguments form a (strictly) increasing sequence 240 * 241 * @param start first number 242 * @param mid second number 243 * @param end third number 244 * @return true if the arguments form an increasing sequence 245 */ 246 protected boolean isSequence(final double start, final double mid, final double end) { 247 return (start < mid) && (mid < end); 248 } 249 250 /** 251 * Verifies that the endpoints specify an interval, 252 * throws IllegalArgumentException if not 253 * 254 * @param lower lower endpoint 255 * @param upper upper endpoint 256 * @throws IllegalArgumentException 257 */ 258 protected void verifyInterval(final double lower, final double upper) { 259 if (lower >= upper) { 260 throw MathRuntimeException.createIllegalArgumentException( 261 LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL, 262 lower, upper); 263 } 264 } 265 266 /** 267 * Verifies that <code>lower < initial < upper</code> 268 * throws IllegalArgumentException if not 269 * 270 * @param lower lower endpoint 271 * @param initial initial value 272 * @param upper upper endpoint 273 * @throws IllegalArgumentException 274 */ 275 protected void verifySequence(final double lower, final double initial, final double upper) { 276 if (!isSequence(lower, initial, upper)) { 277 throw MathRuntimeException.createIllegalArgumentException( 278 LocalizedFormats.INVALID_INTERVAL_INITIAL_VALUE_PARAMETERS, 279 lower, initial, upper); 280 } 281 } 282 283 /** 284 * Verifies that the endpoints specify an interval and the function takes 285 * opposite signs at the endpoints, throws IllegalArgumentException if not 286 * 287 * @param lower lower endpoint 288 * @param upper upper endpoint 289 * @param function function 290 * @throws IllegalArgumentException 291 * @throws FunctionEvaluationException if an error occurs evaluating the function at the endpoints 292 */ 293 protected void verifyBracketing(final double lower, final double upper, 294 final UnivariateRealFunction function) 295 throws FunctionEvaluationException { 296 297 verifyInterval(lower, upper); 298 if (!isBracketing(lower, upper, function)) { 299 throw MathRuntimeException.createIllegalArgumentException( 300 LocalizedFormats.SAME_SIGN_AT_ENDPOINTS, 301 lower, upper, function.value(lower), function.value(upper)); 302 } 303 } 304} 305