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 }