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.analysis.solvers; 019 020 import org.apache.commons.math.ConvergingAlgorithmImpl; 021 import org.apache.commons.math.FunctionEvaluationException; 022 import org.apache.commons.math.MathRuntimeException; 023 import org.apache.commons.math.analysis.UnivariateRealFunction; 024 import org.apache.commons.math.exception.util.LocalizedFormats; 025 import org.apache.commons.math.ConvergenceException; 026 import org.apache.commons.math.exception.NullArgumentException; 027 028 /** 029 * Provide a default implementation for several functions useful to generic 030 * solvers. 031 * 032 * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 f??vr. 2011) $ 033 * @deprecated in 2.2 (to be removed in 3.0). 034 */ 035 @Deprecated 036 public abstract class UnivariateRealSolverImpl 037 extends ConvergingAlgorithmImpl implements UnivariateRealSolver { 038 039 /** Maximum error of function. */ 040 protected double functionValueAccuracy; 041 042 /** Default maximum error of function. */ 043 protected double defaultFunctionValueAccuracy; 044 045 /** Indicates where a root has been computed. */ 046 protected boolean resultComputed = false; 047 048 /** The last computed root. */ 049 protected double result; 050 051 /** Value of the function at the last computed result. */ 052 protected double functionValue; 053 054 /** The function to solve. 055 * @deprecated as of 2.0 the function to solve is passed as an argument 056 * to the {@link #solve(UnivariateRealFunction, double, double)} or 057 * {@link UnivariateRealSolverImpl#solve(UnivariateRealFunction, double, double, double)} 058 * method. */ 059 @Deprecated 060 protected UnivariateRealFunction f; 061 062 /** 063 * Construct a solver with given iteration count and accuracy. 064 * 065 * @param f the function to solve. 066 * @param defaultAbsoluteAccuracy maximum absolute error 067 * @param defaultMaximalIterationCount maximum number of iterations 068 * @throws IllegalArgumentException if f is null or the 069 * defaultAbsoluteAccuracy is not valid 070 * @deprecated as of 2.0 the function to solve is passed as an argument 071 * to the {@link #solve(UnivariateRealFunction, double, double)} or 072 * {@link UnivariateRealSolverImpl#solve(UnivariateRealFunction, double, double, double)} 073 * method. 074 */ 075 @Deprecated 076 protected UnivariateRealSolverImpl(final UnivariateRealFunction f, 077 final int defaultMaximalIterationCount, 078 final double defaultAbsoluteAccuracy) { 079 super(defaultMaximalIterationCount, defaultAbsoluteAccuracy); 080 if (f == null) { 081 throw new NullArgumentException(LocalizedFormats.FUNCTION); 082 } 083 this.f = f; 084 this.defaultFunctionValueAccuracy = 1.0e-15; 085 this.functionValueAccuracy = defaultFunctionValueAccuracy; 086 } 087 088 /** 089 * Construct a solver with given iteration count and accuracy. 090 * 091 * @param defaultAbsoluteAccuracy maximum absolute error 092 * @param defaultMaximalIterationCount maximum number of iterations 093 * @throws IllegalArgumentException if f is null or the 094 * defaultAbsoluteAccuracy is not valid 095 */ 096 protected UnivariateRealSolverImpl(final int defaultMaximalIterationCount, 097 final double defaultAbsoluteAccuracy) { 098 super(defaultMaximalIterationCount, defaultAbsoluteAccuracy); 099 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 }