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