Coverage Report - org.apache.commons.math.analysis.UnivariateRealSolverImpl

Classes in this File Line Coverage Branch Coverage Complexity
UnivariateRealSolverImpl
95% 
100% 
1.636

 1  
 /*
 2  
  * Copyright 2003-2004 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.math.analysis;
 18  
 
 19  
 import java.io.Serializable;
 20  
 
 21  
 import org.apache.commons.math.FunctionEvaluationException;
 22  
 
 23  
 /**
 24  
  * Provide a default implementation for several functions useful to generic
 25  
  * solvers.
 26  
  *  
 27  
  * @version $Revision$ $Date: 2005-08-26 07:05:45 -0700 (Fri, 26 Aug 2005) $
 28  
  */
 29  
 public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
 30  
     Serializable {
 31  
 
 32  
     /** Serializable version identifier */
 33  
     static final long serialVersionUID = 1112491292565386596L;
 34  
     
 35  
     /** Maximum absolute error. */
 36  
     protected double absoluteAccuracy;
 37  
 
 38  
     /** Maximum relative error. */
 39  
     protected double relativeAccuracy;
 40  
 
 41  
     /** Maximum error of function. */
 42  
     protected double functionValueAccuracy;
 43  
 
 44  
     /** Maximum number of iterations. */
 45  
     protected int maximalIterationCount;
 46  
 
 47  
     /** Default maximum absolute error. */
 48  
     protected double defaultAbsoluteAccuracy;
 49  
 
 50  
     /** Default maximum relative error. */
 51  
     protected double defaultRelativeAccuracy;
 52  
 
 53  
     /** Default maximum error of function. */
 54  
     protected double defaultFunctionValueAccuracy;
 55  
 
 56  
     /** Default maximum number of iterations. */
 57  
     protected int defaultMaximalIterationCount;
 58  
 
 59  
     /** Indicates where a root has been computed. */
 60  282
     protected boolean resultComputed = false;
 61  
 
 62  
     /** The last computed root. */
 63  
     protected double result;
 64  
 
 65  
     // Mainly for test framework.
 66  
     /** The last iteration count. */
 67  
     protected int iterationCount;
 68  
 
 69  
     /** The function to solve. */
 70  
     protected UnivariateRealFunction f;
 71  
 
 72  
     /**
 73  
      * Construct a solver with given iteration count and accuracy.
 74  
      * 
 75  
      * @param f the function to solve.
 76  
      * @param defaultAbsoluteAccuracy maximum absolute error
 77  
      * @param defaultMaximalIterationCount maximum number of iterations
 78  
      * @throws IllegalArgumentException if f is null or the 
 79  
      * defaultAbsoluteAccuracy is not valid
 80  
      */
 81  
     protected UnivariateRealSolverImpl(
 82  
         UnivariateRealFunction f,
 83  
         int defaultMaximalIterationCount,
 84  
         double defaultAbsoluteAccuracy) {
 85  
         
 86  282
         super();
 87  
         
 88  282
         if (f == null) {
 89  8
             throw new IllegalArgumentException("function can not be null.");
 90  
         }
 91  
         
 92  274
         this.f = f;
 93  274
         this.defaultAbsoluteAccuracy = defaultAbsoluteAccuracy;
 94  274
         this.defaultRelativeAccuracy = 1E-14;
 95  274
         this.defaultFunctionValueAccuracy = 1E-15;
 96  274
         this.absoluteAccuracy = defaultAbsoluteAccuracy;
 97  274
         this.relativeAccuracy = defaultRelativeAccuracy;
 98  274
         this.functionValueAccuracy = defaultFunctionValueAccuracy;
 99  274
         this.defaultMaximalIterationCount = defaultMaximalIterationCount;
 100  274
         this.maximalIterationCount = defaultMaximalIterationCount;
 101  274
     }
 102  
 
 103  
     /**
 104  
      * Access the last computed root.
 105  
      * 
 106  
      * @return the last computed root
 107  
      * @throws IllegalStateException if no root has been computed
 108  
      */
 109  
     public double getResult() {
 110  6
         if (resultComputed) {
 111  6
             return result;
 112  
         } else {
 113  0
             throw new IllegalStateException("No result available");
 114  
         }
 115  
     }
 116  
 
 117  
     /**
 118  
      * Access the last iteration count.
 119  
      * 
 120  
      * @return the last iteration count
 121  
      * @throws IllegalStateException if no root has been computed
 122  
      *  
 123  
      */
 124  
     public int getIterationCount() {
 125  56
         if (resultComputed) {
 126  56
             return iterationCount;
 127  
         } else {
 128  0
             throw new IllegalStateException("No result available");
 129  
         }
 130  
     }
 131  
 
 132  
     /**
 133  
      * Convenience function for implementations.
 134  
      * 
 135  
      * @param result the result to set
 136  
      * @param iterationCount the iteration count to set
 137  
      */
 138  
     protected final void setResult(double result, int iterationCount) {
 139  396
         this.result = result;
 140  396
         this.iterationCount = iterationCount;
 141  396
         this.resultComputed = true;
 142  396
     }
 143  
 
 144  
     /**
 145  
      * Convenience function for implementations.
 146  
      */
 147  
     protected final void clearResult() {
 148  346
         this.resultComputed = false;
 149  346
     }
 150  
 
 151  
     /**
 152  
      * Set the absolute accuracy.
 153  
      * 
 154  
      * @param accuracy the accuracy.
 155  
      * @throws IllegalArgumentException if the accuracy can't be achieved by
 156  
      *  the solver or is otherwise deemed unreasonable. 
 157  
      */
 158  
     public void setAbsoluteAccuracy(double accuracy) {
 159  10
         absoluteAccuracy = accuracy;
 160  10
     }
 161  
 
 162  
     /**
 163  
      * Get the actual absolute accuracy.
 164  
      * 
 165  
      * @return the accuracy
 166  
      */
 167  
     public double getAbsoluteAccuracy() {
 168  226
         return absoluteAccuracy;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Reset the absolute accuracy to the default.
 173  
      */
 174  
     public void resetAbsoluteAccuracy() {
 175  2
         absoluteAccuracy = defaultAbsoluteAccuracy;
 176  2
     }
 177  
 
 178  
     /**
 179  
      * Set the upper limit for the number of iterations.
 180  
      * 
 181  
      * @param count maximum number of iterations
 182  
      */
 183  
     public void setMaximalIterationCount(int count) {
 184  4
         maximalIterationCount = count;
 185  4
     }
 186  
 
 187  
     /**
 188  
      * Get the upper limit for the number of iterations.
 189  
      * 
 190  
      * @return the actual upper limit
 191  
      */
 192  
     public int getMaximalIterationCount() {
 193  6
         return maximalIterationCount;
 194  
     }
 195  
 
 196  
     /**
 197  
      * Reset the upper limit for the number of iterations to the default.
 198  
      */
 199  
     public void resetMaximalIterationCount() {
 200  2
         maximalIterationCount = defaultMaximalIterationCount;
 201  2
     }
 202  
 
 203  
     /**
 204  
      * Set the relative accuracy.
 205  
      * 
 206  
      * @param accuracy the relative accuracy.
 207  
      * @throws IllegalArgumentException if the accuracy can't be achieved by
 208  
      *  the solver or is otherwise deemed unreasonable. 
 209  
      */
 210  
     public void setRelativeAccuracy(double accuracy) {
 211  8
         relativeAccuracy = accuracy;
 212  8
     }
 213  
 
 214  
     /**
 215  
      * Get the actual relative accuracy.
 216  
      * @return the accuracy
 217  
      */
 218  
     public double getRelativeAccuracy() {
 219  84
         return relativeAccuracy;
 220  
     }
 221  
 
 222  
     /**
 223  
      * Reset the relative accuracy to the default.
 224  
      */
 225  
     public void resetRelativeAccuracy() {
 226  6
         relativeAccuracy = defaultRelativeAccuracy;
 227  6
     }
 228  
 
 229  
     /**
 230  
      * Set the function value accuracy.
 231  
      * 
 232  
      * @param accuracy the accuracy.
 233  
      * @throws IllegalArgumentException if the accuracy can't be achieved by
 234  
      * the solver or is otherwise deemed unreasonable. 
 235  
      */
 236  
     public void setFunctionValueAccuracy(double accuracy) {
 237  4
         functionValueAccuracy = accuracy;
 238  4
     }
 239  
 
 240  
     /**
 241  
      * Get the actual function value accuracy.
 242  
      * @return the accuracy
 243  
      */
 244  
     public double getFunctionValueAccuracy() {
 245  6
         return functionValueAccuracy;
 246  
     }
 247  
 
 248  
     /**
 249  
      * Reset the actual function accuracy to the default.
 250  
      */
 251  
     public void resetFunctionValueAccuracy() {
 252  2
         functionValueAccuracy = defaultFunctionValueAccuracy;
 253  2
     }
 254  
     
 255  
     
 256  
     /**
 257  
      * Returns true iff the function takes opposite signs at the endpoints.
 258  
      * 
 259  
      * @param lower  the lower endpoint 
 260  
      * @param upper  the upper endpoint
 261  
      * @param f the function
 262  
      * @return true if f(lower) * f(upper) < 0
 263  
      * @throws FunctionEvaluationException if an error occurs evaluating the 
 264  
      * function at the endpoints
 265  
      */
 266  
     protected boolean isBracketing(double lower, double upper, 
 267  
             UnivariateRealFunction f) throws FunctionEvaluationException {
 268  66
             double f1 = f.value(lower);
 269  66
             double f2 = f.value(upper);
 270  66
             return ((f1 > 0 && f2 < 0) || (f1 < 0 && f2 > 0));
 271  
     }
 272  
     
 273  
     /**
 274  
      * Returns true if the arguments form a (strictly) increasing sequence
 275  
      * 
 276  
      * @param start  first number
 277  
      * @param mid   second number
 278  
      * @param end  third number
 279  
      * @return true if the arguments form an increasing sequence
 280  
      */
 281  
     protected boolean isSequence(double start, double mid, double end) {
 282  140
         return (start < mid) && (mid < end);
 283  
     }
 284  
     
 285  
     /**
 286  
      * Verifies that the endpoints specify an interval, 
 287  
      * throws IllegalArgumentException if not
 288  
      * 
 289  
      * @param lower  lower endpoint
 290  
      * @param upper upper endpoint
 291  
      * @throws IllegalArgumentException
 292  
      */
 293  
     protected void verifyInterval(double lower, double upper) {
 294  414
         if (lower >= upper) {
 295  8
             throw new IllegalArgumentException
 296  
                 ("Endpoints do not specify an interval: [" + lower + 
 297  
                         "," + upper + "]");
 298  
         }       
 299  406
     }
 300  
     
 301  
     /**
 302  
      * Verifies that <code>lower < initial < upper</code>
 303  
      * throws IllegalArgumentException if not
 304  
      * 
 305  
      * @param lower  lower endpoint
 306  
      * @param initial initial value
 307  
      * @param upper upper endpoint
 308  
      * @throws IllegalArgumentException
 309  
      */
 310  
     protected void verifySequence(double lower, double initial, double upper) {
 311  4
         if (!isSequence(lower, initial, upper)) {
 312  0
             throw new IllegalArgumentException
 313  
                 ("Invalid interval, initial value parameters:  lower=" + 
 314  
                    lower + " initial=" + initial + " upper=" + upper);
 315  
         }       
 316  4
     }
 317  
     
 318  
     /**
 319  
      * Verifies that the endpoints specify an interval and the function takes
 320  
      * opposite signs at the enpoints, throws IllegalArgumentException if not
 321  
      * 
 322  
      * @param lower  lower endpoint
 323  
      * @param upper upper endpoint
 324  
      * @param f function
 325  
      * @throws IllegalArgumentException
 326  
      * @throws FunctionEvaluationException if an error occurs evaluating the 
 327  
      * function at the endpoints
 328  
      */
 329  
     protected void verifyBracketing(double lower, double upper, 
 330  
             UnivariateRealFunction f) throws FunctionEvaluationException {
 331  
         
 332  72
         verifyInterval(lower, upper);
 333  66
         if (!isBracketing(lower, upper, f)) {
 334  6
             throw new IllegalArgumentException
 335  
             ("Function values at endpoints do not have different signs." +
 336  
                     "  Endpoints: [" + lower + "," + upper + "]" + 
 337  
                     "  Values: [" + f.value(lower) + "," + f.value(upper) + "]");       
 338  
         }
 339  60
     }
 340  
 }