diff --git a/src/java/org/apache/commons/math/analysis/BrentSolver.java b/src/java/org/apache/commons/math/analysis/BrentSolver.java new file mode 100644 index 000000000..6541c3e95 --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/BrentSolver.java @@ -0,0 +1,197 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.MathException; + +/** + * Provide the Brent algorithm for solving for zeros of real univariate + * functions. + * It will only search for one zero in the given interval. + * The function is supposed to be continuous but not necessarily smooth. + * + * @author pietsch at apache.org + */ +public class BrentSolver extends UnivariateRealSolverImpl { + + private UnivariateRealFunction f; + + public BrentSolver(UnivariateRealFunction f) { + super(100, 1E-6); + this.f = f; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#solve(double, double) + */ + public double solve(double min, double max) throws MathException { + clearResult(); + // Index 0 is the old approximation for the root. + // Index 1 is the last calculated approximation for the root. + // Index 2 is a bracket for the root with respect to x1. + double x0 = min; + double x1 = max; + double y0 = f.value(x0); + double y1 = f.value(x1); + if ((y0 > 0) == (y1 > 0)) { + throw new MathException("Interval doesn't bracket a zero."); + } + double x2 = x0; + double y2 = y0; + double delta = x1 - x0; + double oldDelta = delta; + + int i = 0; + while (i < maximalIterationCount) { + if (Math.abs(y2) < Math.abs(y1)) { + x0 = x1; + x1 = x2; + x2 = x0; + y0 = y1; + y1 = y2; + y2 = y0; + } + if (Math.abs(y1) <= functionValueAccuracy) { + // Avoid division by very small values. Assume + // the iteration has converged (the problem may + // still be ill conditioned) + setResult(x1, i); + return result; + } + double dx = (x2 - x1); + double tolerance = + Math.max(relativeAccuracy * Math.abs(x1), absoluteAccuracy); + if (Math.abs(dx) <= tolerance) { + setResult(x1, i); + return result; + } +// System.out.println( +// " x0=" +// + x0 +// + " y0=" +// + y0 +// + " x1=" +// + x1 +// + " y1=" +// + y1 +// + " x2=" +// + x2+" y2="+y2); +// System.out.println(" dx="+dx+" delta: "+delta+" olddelta: "+oldDelta); + if (Math.abs(oldDelta) < tolerance + || Math.abs(y0) <= Math.abs(y1)) { +// System.out.println("bisection"); + // Force bisection. + delta = 0.5 * dx; + oldDelta = delta; + } else { + double r3 = y1 / y0; + double p; + double p1; + if (x0 == x2) { + // Linear interpolation. +// System.out.println("linear"); + p = dx * r3; + p1 = 1.0 - r3; + } else { + // Inverse quadratic interpolation. +// System.out.println("invers quad"); + double r1 = y0 / y2; + double r2 = y1 / y2; + p = r3 * (dx * r1 * (r1 - r2) - (x1 - x0) * (r2 - 1.0)); + p1 = (r1 - 1.0) * (r2 - 1.0) * (r3 - 1.0); + } + if (p > 0.0) { + p1 = -p1; + } else { + p = -p; + } +// System.out.println(" p="+p+" p1="+p1+" qq: "+(1.5 * dx * p1 - Math.abs(tolerance * p1))); +// System.out.println(" p="+p+" q: "+p1+" ad="+Math.abs(0.5 * oldDelta * p1)); + if (2.0 * p >= 1.5 * dx * p1 - Math.abs(tolerance * p1) + || p >= Math.abs(0.5 * oldDelta * p1)) { + // Inverse quadratic interpolation gives a value + // in the wrong direction, or progress is slow. + // Fall back to bisection. +// System.out.println("bisection fallback"); + delta = 0.5 * dx; + oldDelta = delta; + } else { + oldDelta = delta; + delta = p / p1; + } + } + // Save old X1, Y1 + x0 = x1; + y0 = y1; + // Compute new X1, Y1 + if (Math.abs(delta) > tolerance) { + x1 = x1 + delta; + } else if (dx > 0.0) { + x1 = x1 + 0.5*tolerance; + } else if (dx <= 0.0) { + x1 = x1 - 0.5*tolerance; + } + y1 = f.value(x1); + if ((y1 > 0) == (y2 > 0)) { + x2 = x0; + y2 = y0; + delta = x1 - x0; + oldDelta = delta; + } + i++; + } + throw new MathException("Maximal iteration number exceeded."); + } + +} diff --git a/src/java/org/apache/commons/math/analysis/SecantSolver.java b/src/java/org/apache/commons/math/analysis/SecantSolver.java new file mode 100644 index 000000000..140261bcf --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/SecantSolver.java @@ -0,0 +1,145 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.MathException; + +/** + * Provide the secant algorithm for solving for zeros of real univariate + * functions. Because of forced bracketing, convergence is slower than + * the unrestricted secant algorithm. However, slow convergence of the + * Regula Falsi can be avoided. + * It will only search for one zero in the given interval. + * The function is supposed to be continuous but not necessarily smooth. + * + * @author pietsch at apache.org + */ +public class SecantSolver extends UnivariateRealSolverImpl { + + private UnivariateRealFunction f; + + public SecantSolver(UnivariateRealFunction f) { + super(100, 1E-6); + this.f = f; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#solve(double, double) + */ + public double solve(double min, double max) throws MathException { + clearResult(); + // Index 0 is the old approximation for the root. + // Index 1 is the last calculated approximation for the root. + // Index 2 is a bracket for the root with respect to x0. + // OldDelta is the length of the bracketing interval of the last + // iteration. + double x0 = min; + double x1 = max; + double y0 = f.value(x0); + double y1 = f.value(x1); + if ((y0>0)== (y1>0)) { + throw new MathException("Interval doesn't bracket a zero."); + } + double x2 = x0; + double y2 = y0; + double oldDelta = x2 - x1; + int i = 0; + while (i < maximalIterationCount) { + if (Math.abs(y2) < Math.abs(y1)) { + x0 = x1; + x1 = x2; + x2 = x0; + y0 = y1; + y1 = y2; + y2 = y0; + } + if (Math.abs(y1) <= functionValueAccuracy) { + setResult(x1, i); + return result; + } + if (Math.abs(oldDelta) + < Math.max(relativeAccuracy * Math.abs(x1), absoluteAccuracy)) { + setResult(x1, i); + return result; + } + double delta; + if (Math.abs(y1) > Math.abs(y0)) { + // Function value increased in last iteration. Force bisection. + delta = 0.5 * oldDelta; +// System.out.println("Forced Bisection"); + } else { + delta = (x0 - x1) / (1 - y0 / y1); + // System.out.println("delta=" + delta + " olddelta=" + oldDelta); + if (delta / oldDelta > 1) { + // New approximation falls outside bracket. Fall back to bisection. + delta = 0.5 * oldDelta; +// System.out.println("Fallback Bisection"); + } + } + x0 = x1; + y0 = y1; + x1 = x1 + delta; + y1 = f.value(x1); + if ((y1>0) == (y2>0)) { + // New bracket is (x0,x1). + x2 = x0; + y2 = y0; + } + oldDelta = x2 - x1; + i++; + } + throw new MathException("Maximal iteration number exceeded"); + } + +} diff --git a/src/java/org/apache/commons/math/analysis/UnivariateRealFunction.java b/src/java/org/apache/commons/math/analysis/UnivariateRealFunction.java new file mode 100644 index 000000000..182055e24 --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/UnivariateRealFunction.java @@ -0,0 +1,110 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.MathException; + +/** + * Provide an interface univariate real functions. + * The object may held temporary data which is shared between calculations + * of the value and the derivatives for the same argument. It is not guaranteed + * that derivatives are evaluated after the value, the evaluation algorithm + * should throw an InvalidStateException if it can't cope with this. + * + * @author pietsch at apache.org + */ +public interface UnivariateRealFunction { + + /** + * Compute the value for the function. + * @param x the point for which the function value should be computed + * @return the value + * @throws MathException if the function couldn't be computed due to + * missing additional data or other environmental problems. + * @throws RuntimeException if the operation isn't supported, the argument + * was outside the supported domain or any other problem. + * + */ + public double value(double x) throws MathException; + + /** + * Compute the value for the first derivative of the function. + * It is recommended to provide this method only if the first derivative is + * analytical. Numerical derivatives may be acceptable in some cases. + * An implementation should throw an UnsupportedOperationException if + * this method is not implemented. + * @param x the point for which the first derivative should be computed + * @return the value + * @throws MathException if the derivative couldn't be computed. + * @throws RuntimeException if the operation isn't supported, the argument + * was outside the supported domain or any other problem. + * + */ + public double firstDerivative(double x) throws MathException; + + /** + * Compute the value for the second derivative of the function. + * It is recommended to provide this method only if the second derivative is + * analytical. Numerical derivatives may be acceptable in some cases. + * An implementation should throw an UnsupportedOperationException if + * this method is not implemented. + * @param x the point for which the first derivative should be computed + * @return the value + * @throws MathException if the second derivative couldn't be computed. + * @throws RuntimeException if the operation isn't supported, the argument + * was outside the supported domain or any other problem. + * + */ + public double secondDerivative(double x) throws MathException; +} diff --git a/src/java/org/apache/commons/math/analysis/UnivariateRealSolver.java b/src/java/org/apache/commons/math/analysis/UnivariateRealSolver.java new file mode 100644 index 000000000..c8669d451 --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/UnivariateRealSolver.java @@ -0,0 +1,209 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.MathException; + +/** + * Provide an interface to algorithms for solving for zeros of real univariate + * functions. + * An implementation will only search for one zero in the given interval. + * + * @author pietsch at apache.org + */ +public interface UnivariateRealSolver { + + /** + * Set the upper limit for the number of iterations. + * Usually a high iteration count indicates convergence problems. However, + * the "reasonable value" varies widely for different solvers, users are + * advised to use the default value supplied by the solver. + * An exception will be thrown if the number is exceeded. + * + * @param count + */ + public void setMaximalIterationCount(int count); + + /** + * Get the upper limit for the number of iterations. + * @return the actual upper limit + */ + public int getMaximalIterationCount(); + + /** + * Reset the upper limit for the number of iterations to the default. + * The default value is supplied by the solver implementation. + * + * @see #setMaximalIterationCount(int) + */ + public void resetMaximalIterationCount(); + + /** + * Set the absolute accuracy. + * The default is usually choosen so taht roots in the interval + * -10..-0.1 and +0.1..+10 can be found wit a reasonable accuracy. If the expected + * absolute value of your roots is of much smaller magnitude, set this to a smaller + * value. + * Solvers are advised to do a plausibility check with the relative accuracy, but + * clients should not rely on this. + * @param accuracy the accuracy. + * @throws MathException if the accuracy can't be achieved by the solver or is + * otherwise deemed unreasonable. + */ + public void setAbsoluteAccuracy(double accuracy) throws MathException; + + /** + * Get the actual absolute accuracy. + * @return the accuracy + */ + public double getAbsoluteAccuracy(); + + /** + * Reset the absolute accuracy to the default. + * The default value is provided by the solver implementation. + */ + public void resetAbsoluteAccuracy(); + + /** + * Set the relative accuracy. + * This is used to stop iterations if the absolute accuracy can't be achieved + * due to large values or short mantissa length. + * If this should be the primary criterium for convergence rather then a safety + * measure, set the absolute accuracy to a ridiculously small value, like 1E-1000. + * @param accuracy the relative accuracy. + * @throws MathException if the accuracy can't be achieved by the solver or is + * otherwise deemed unreasonable. + */ + public void setRelativeAccuracy(double Accuracy) throws MathException; + + /** + * Get the actual relative accuracy. + * @return the accuracy + */ + public double getRelativeAccuracy(); + + /** + * Reset the relative accuracy to the default. + * The default value is provided by the solver implementation. + */ + public void resetRelativeAccuracy(); + + /** + * Set the function value accuracy. + * This is used to determine whan an evaluated function value or some other + * value which is used as divisor is zero. + * This is a safety guard and it shouldn't be necesary to change this in general. + * @param accuracy the accuracy. + * @throws MathException if the accuracy can't be achieved by the solver or is + * otherwise deemed unreasonable. + */ + public void setFunctionValueAccuracy(double Accuracy) throws MathException; + + /** + * Get the actual function value accuracy. + * @return the accuracy + */ + public double getFunctionValueAccuracy(); + + /** + * Reset the actual function accuracy to the default. + * The default value is provided by the solver implementation. + */ + public void resetFunctionValueAccuracy(); + + /** + * Solve for a zero root in the given interval. + * A solver may require that the interval brackets a single zero root. + * @param min the lower bound for the interval. + * @param max the upper bound for the interval. + * @return the value where the function is zero + * @throws MathException if the iteration count was exceeded or the + * solver detects convergence problems otherwise. + */ + public double solve(double min, double max) throws MathException; + + /** + * Solve for a zero in the given interval, start at startValue. + * A solver may require that the interval brackets a single zero root. + * @param min the lower bound for the interval. + * @param max the upper bound for the interval. + * @param startValue the start value to use + * @return the value where the function is zero + * @throws MathException if the iteration count was exceeded or the + * solver detects convergence problems otherwise. + */ + public double solve(double min, double max, double startValue) + throws MathException; + + /** + * Get the result of the last run of the solver. + * @return the last result. + * @throws MathException if there is no result available, either + * because no result was yet computed or the last attempt failed. + */ + public double getResult() throws MathException; + + /** + * Get the number of iterations in the last run of the solver. + * This is mainly meant for testing purposes. It may occasionally + * help track down performance problems: if the iteration count + * is notoriously high, check whether the function is evaluated + * properly, and whether another solver is more amenable to the + * problem. + * @return the last iteration count. + * @throws MathException if there is no result available, either + * because no result was yet computed or the last attempt failed. + */ + public int getIterationCount() throws MathException; +} \ No newline at end of file diff --git a/src/java/org/apache/commons/math/analysis/UnivariateRealSolverFactory.java b/src/java/org/apache/commons/math/analysis/UnivariateRealSolverFactory.java new file mode 100644 index 000000000..abeb3440a --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/UnivariateRealSolverFactory.java @@ -0,0 +1,136 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.math.analysis; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.commons.math.MathConfigurationException; +import org.apache.commons.math.MathException; + +/** + * @author pietsch at apache.org + * + * A factory to easily get a default solver and some convenience + * functions. + * Because solvers are easily reusable, the factory does not + * store configuration data and creates preconfigured solvers + * (this may be controversial, because the configuration data + * may also be used for the default solver used by the static + * solve() method). + * + */ +public class UnivariateRealSolverFactory { + protected UnivariateRealSolverFactory() { + } + + public static UnivariateRealSolver newSolver(UnivariateRealFunction f) + throws MathConfigurationException { + String solverClassName = + System.getProperty( + "org.apache.commons.math.analysis.UnivariateRealSolver", + "org.apache.commons.math.analysis.BrentSolver"); + try { + Class clazz = Class.forName(solverClassName); + Class paramClass[] = new Class[1]; + paramClass[0] = + Class.forName("org.apache.commons.math.analysis.UnivariateRealFunction"); + Object param[] = new Object[1]; + param[0] = f; + return (UnivariateRealSolver)clazz.getConstructor( + paramClass).newInstance( + param); + } catch (IllegalArgumentException e) { + throw new MathConfigurationException(e); + } catch (SecurityException e) { + throw new MathConfigurationException( + "Can't access " + solverClassName, + e); + } catch (ClassNotFoundException e) { + throw new MathConfigurationException( + "Class not found: " + solverClassName, + e); + } catch (InstantiationException e) { + throw new MathConfigurationException( + "Can't instantiate " + solverClassName, + e); + } catch (IllegalAccessException e) { + throw new MathConfigurationException( + "Can't access " + solverClassName, + e); + } catch (InvocationTargetException e) { + throw new MathConfigurationException(e); + } catch (NoSuchMethodException e) { + throw new MathConfigurationException( + "No constructor with UnivariateRealFunction in " + + solverClassName, + e); + } + } + + public static double solve(UnivariateRealFunction f, double x0, double x1) + throws MathException { + return newSolver(f).solve(x0, x1); + } + + public static double solve( + UnivariateRealFunction f, + double x0, + double x1, + double absoluteAccuracy) + throws MathException { + UnivariateRealSolver solver = newSolver(f); + solver.setAbsoluteAccuracy(absoluteAccuracy); + return solver.solve(x0, x1); + } +} diff --git a/src/java/org/apache/commons/math/analysis/UnivariateRealSolverImpl.java b/src/java/org/apache/commons/math/analysis/UnivariateRealSolverImpl.java new file mode 100644 index 000000000..3c825b868 --- /dev/null +++ b/src/java/org/apache/commons/math/analysis/UnivariateRealSolverImpl.java @@ -0,0 +1,238 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.commons.math.analysis; + +import org.apache.commons.math.MathException; + +/** + * Provide a default implementation for several functions useful to generic + * solvers. + * + * @author pietsch at apache.org + */ +public abstract class UnivariateRealSolverImpl + implements UnivariateRealSolver { + + protected double absoluteAccuracy; + protected double relativeAccuracy; + protected double functionValueAccuracy; + protected int maximalIterationCount; + + protected double defaultAbsoluteAccuracy; + protected double defaultRelativeAccuracy; + protected double defaultFunctionValueAccuracy; + protected int defaultMaximalIterationCount; + + protected boolean resultComputed = false; + protected double result; + // Mainly for test framework. + protected int iterationCount; + + protected UnivariateRealSolverImpl( + int defaultMaximalIterationCount, + double defaultAbsoluteAccuracy) { + this.defaultAbsoluteAccuracy = defaultAbsoluteAccuracy; + this.defaultRelativeAccuracy = 1E-14; + this.defaultFunctionValueAccuracy = 1E-15; + this.absoluteAccuracy = defaultAbsoluteAccuracy; + this.relativeAccuracy = defaultRelativeAccuracy; + this.functionValueAccuracy = defaultFunctionValueAccuracy; + this.defaultMaximalIterationCount = defaultMaximalIterationCount; + this.maximalIterationCount = defaultMaximalIterationCount; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#solve(double, double) + */ + public double solve(double min, double max) throws MathException { + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#solve(double, double, double) + */ + public double solve(double min, double max, double startValue) + throws MathException { + throw new UnsupportedOperationException(); + } + + /* + * Get result of last solver run. + * @see org.apache.commons.math.UnivariateRealSolver#getResult() + */ + public double getResult() throws MathException { + if (resultComputed) { + return result; + } else { + throw new MathException("No result available"); + } + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#getIterationCount() + */ + public int getIterationCount() throws MathException { + if (resultComputed) { + return iterationCount; + } else { + throw new MathException("No result available"); + } + } + + /* + * Convenience function for implementations. + * @param result the result to set + * @param iteratinCount the iteration count to set + */ + protected final void setResult(double result, int iterationCount) { + this.result = result; + this.iterationCount = iterationCount; + this.resultComputed = true; + } + + /* + * Convenience function for implementations. + */ + protected final void clearResult() { + this.resultComputed = false; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#setAccuracy(double) + */ + public void setAbsoluteAccuracy(double accuracy) + throws MathException { + absoluteAccuracy = accuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#getAccuracy() + */ + public double getAbsoluteAccuracy() { + return absoluteAccuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#resetAbsoluteAccuracy() + */ + public void resetAbsoluteAccuracy() { + absoluteAccuracy = defaultAbsoluteAccuracy; + } + + /* Set maximum iteration count. + * @see org.apache.commons.math.UnivariateRealSolver#setMaximalIterationCount(int) + */ + public void setMaximalIterationCount(int count) { + maximalIterationCount = count; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#getMaximalIterationCount() + */ + public int getMaximalIterationCount() { + return maximalIterationCount; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#resetMaximalIterationCount() + */ + public void resetMaximalIterationCount() { + maximalIterationCount = defaultMaximalIterationCount; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#setRelativeAccuracy(double) + */ + public void setRelativeAccuracy(double accuracy) throws MathException { + relativeAccuracy = accuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#getRelativeAccuracy() + */ + public double getRelativeAccuracy() { + return relativeAccuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#resetRelativeAccuracy() + */ + public void resetRelativeAccuracy() { + relativeAccuracy = defaultRelativeAccuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#setFunctionValueAccuracy(double) + */ + public void setFunctionValueAccuracy(double accuracy) + throws MathException { + functionValueAccuracy = accuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#getFunctionValueAccuracy() + */ + public double getFunctionValueAccuracy() { + return functionValueAccuracy; + } + + /* (non-Javadoc) + * @see org.apache.commons.math.UnivariateRealSolver#resetFunctionValueAccuracy() + */ + public void resetFunctionValueAccuracy() { + functionValueAccuracy = defaultFunctionValueAccuracy; + } + +}