Home | History | Annotate | Download | only in solvers
      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.analysis.solvers;
     19 
     20 import org.apache.commons.math.ConvergingAlgorithmImpl;
     21 import org.apache.commons.math.FunctionEvaluationException;
     22 import org.apache.commons.math.MathRuntimeException;
     23 import org.apache.commons.math.analysis.UnivariateRealFunction;
     24 import org.apache.commons.math.exception.util.LocalizedFormats;
     25 import org.apache.commons.math.ConvergenceException;
     26 import 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 fvr. 2011) $
     33  * @deprecated in 2.2 (to be removed in 3.0).
     34  */
     35 @Deprecated
     36 public 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