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    package org.apache.commons.math.analysis.solvers;
018    
019    import org.apache.commons.math.MathException;
020    import org.apache.commons.math.analysis.Expm1Function;
021    import org.apache.commons.math.analysis.QuinticFunction;
022    import org.apache.commons.math.analysis.SinFunction;
023    import org.apache.commons.math.analysis.UnivariateRealFunction;
024    
025    import junit.framework.TestCase;
026    
027    /**
028     * Testcase for Ridders solver.
029     * <p>
030     * Ridders' method converges superlinearly, more specific, its rate of
031     * convergence is sqrt(2). Test runs show that for a default absolute
032     * accuracy of 1E-6, it generally takes less than 5 iterations for close
033     * initial bracket and 5 to 10 iterations for distant initial bracket
034     * to converge.
035     * 
036     * @version $Revision: 799857 $ $Date: 2009-08-01 09:07:12 -0400 (Sat, 01 Aug 2009) $ 
037     */
038    public final class RiddersSolverTest extends TestCase {
039    
040        /**
041         * Test the deprecated APIs.
042         */
043        @Deprecated
044        public void testDeprecated() throws MathException {
045            UnivariateRealFunction f = new SinFunction();
046            UnivariateRealSolver solver = new RiddersSolver(f);
047            double min, max, expected, result, tolerance;
048    
049            min = 3.0; max = 4.0; expected = Math.PI;
050            tolerance = Math.max(solver.getAbsoluteAccuracy(),
051                        Math.abs(expected * solver.getRelativeAccuracy()));
052            result = solver.solve(min, max);
053            assertEquals(expected, result, tolerance);
054    
055            min = -1.0; max = 1.5; expected = 0.0;
056            tolerance = Math.max(solver.getAbsoluteAccuracy(),
057                        Math.abs(expected * solver.getRelativeAccuracy()));
058            result = solver.solve(min, max);
059            assertEquals(expected, result, tolerance);
060        }
061    
062        /**
063         * Test of solver for the sine function.
064         */
065        public void testSinFunction() throws MathException {
066            UnivariateRealFunction f = new SinFunction();
067            UnivariateRealSolver solver = new RiddersSolver();
068            double min, max, expected, result, tolerance;
069    
070            min = 3.0; max = 4.0; expected = Math.PI;
071            tolerance = Math.max(solver.getAbsoluteAccuracy(),
072                        Math.abs(expected * solver.getRelativeAccuracy()));
073            result = solver.solve(f, min, max);
074            assertEquals(expected, result, tolerance);
075    
076            min = -1.0; max = 1.5; expected = 0.0;
077            tolerance = Math.max(solver.getAbsoluteAccuracy(),
078                        Math.abs(expected * solver.getRelativeAccuracy()));
079            result = solver.solve(f, min, max);
080            assertEquals(expected, result, tolerance);
081        }
082    
083        /**
084         * Test of solver for the quintic function.
085         */
086        public void testQuinticFunction() throws MathException {
087            UnivariateRealFunction f = new QuinticFunction();
088            UnivariateRealSolver solver = new RiddersSolver();
089            double min, max, expected, result, tolerance;
090    
091            min = -0.4; max = 0.2; expected = 0.0;
092            tolerance = Math.max(solver.getAbsoluteAccuracy(),
093                        Math.abs(expected * solver.getRelativeAccuracy()));
094            result = solver.solve(f, min, max);
095            assertEquals(expected, result, tolerance);
096    
097            min = 0.75; max = 1.5; expected = 1.0;
098            tolerance = Math.max(solver.getAbsoluteAccuracy(),
099                        Math.abs(expected * solver.getRelativeAccuracy()));
100            result = solver.solve(f, min, max);
101            assertEquals(expected, result, tolerance);
102    
103            min = -0.9; max = -0.2; expected = -0.5;
104            tolerance = Math.max(solver.getAbsoluteAccuracy(),
105                        Math.abs(expected * solver.getRelativeAccuracy()));
106            result = solver.solve(f, min, max);
107            assertEquals(expected, result, tolerance);
108        }
109    
110        /**
111         * Test of solver for the exponential function.
112         */
113        public void testExpm1Function() throws MathException {
114            UnivariateRealFunction f = new Expm1Function();
115            UnivariateRealSolver solver = new RiddersSolver();
116            double min, max, expected, result, tolerance;
117    
118            min = -1.0; max = 2.0; expected = 0.0;
119            tolerance = Math.max(solver.getAbsoluteAccuracy(),
120                        Math.abs(expected * solver.getRelativeAccuracy()));
121            result = solver.solve(f, min, max);
122            assertEquals(expected, result, tolerance);
123    
124            min = -20.0; max = 10.0; expected = 0.0;
125            tolerance = Math.max(solver.getAbsoluteAccuracy(),
126                        Math.abs(expected * solver.getRelativeAccuracy()));
127            result = solver.solve(f, min, max);
128            assertEquals(expected, result, tolerance);
129    
130            min = -50.0; max = 100.0; expected = 0.0;
131            tolerance = Math.max(solver.getAbsoluteAccuracy(),
132                        Math.abs(expected * solver.getRelativeAccuracy()));
133            result = solver.solve(f, min, max);
134            assertEquals(expected, result, tolerance);
135        }
136    
137        /**
138         * Test of parameters for the solver.
139         */
140        public void testParameters() throws Exception {
141            UnivariateRealFunction f = new SinFunction();
142            UnivariateRealSolver solver = new RiddersSolver();
143    
144            try {
145                // bad interval
146                solver.solve(f, 1, -1);
147                fail("Expecting IllegalArgumentException - bad interval");
148            } catch (IllegalArgumentException ex) {
149                // expected
150            }
151            try {
152                // no bracketing
153                solver.solve(f, 2, 3);
154                fail("Expecting IllegalArgumentException - no bracketing");
155            } catch (IllegalArgumentException ex) {
156                // expected
157            }
158        }
159    }