View Javadoc
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.math4.legacy.analysis.solvers;
19  
20  import org.apache.commons.math4.legacy.analysis.QuinticFunction;
21  import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
22  import org.apache.commons.math4.legacy.analysis.function.Sin;
23  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
24  import org.apache.commons.math4.legacy.exception.NoBracketingException;
25  import org.apache.commons.math4.legacy.exception.NullArgumentException;
26  import org.apache.commons.math4.core.jdkmath.JdkMath;
27  import org.junit.Assert;
28  import org.junit.Test;
29  
30  /**
31   */
32  public class UnivariateSolverUtilsTest {
33  
34      protected UnivariateFunction sin = new Sin();
35  
36      @Test(expected=NullArgumentException.class)
37      public void testSolveNull() {
38          UnivariateSolverUtils.solve(null, 0.0, 4.0);
39      }
40  
41      @Test(expected=MathIllegalArgumentException.class)
42      public void testSolveBadEndpoints() {
43          double root = UnivariateSolverUtils.solve(sin, 4.0, -0.1, 1e-6);
44          System.out.println("root=" + root);
45      }
46  
47      @Test
48      public void testSolveBadAccuracy() {
49          try { // bad accuracy
50              UnivariateSolverUtils.solve(sin, 0.0, 4.0, 0.0);
51  //             Assert.fail("Expecting MathIllegalArgumentException"); // TODO needs rework since convergence behaviour was changed
52          } catch (MathIllegalArgumentException ex) {
53              // expected
54          }
55      }
56  
57      @Test
58      public void testSolveSin() {
59          double x = UnivariateSolverUtils.solve(sin, 1.0, 4.0);
60          Assert.assertEquals(JdkMath.PI, x, 1.0e-4);
61      }
62  
63      @Test(expected=NullArgumentException.class)
64      public void testSolveAccuracyNull()  {
65          double accuracy = 1.0e-6;
66          UnivariateSolverUtils.solve(null, 0.0, 4.0, accuracy);
67      }
68  
69      @Test
70      public void testSolveAccuracySin() {
71          double accuracy = 1.0e-6;
72          double x = UnivariateSolverUtils.solve(sin, 1.0,
73                  4.0, accuracy);
74          Assert.assertEquals(JdkMath.PI, x, accuracy);
75      }
76  
77      @Test(expected=MathIllegalArgumentException.class)
78      public void testSolveNoRoot() {
79          UnivariateSolverUtils.solve(sin, 1.0, 1.5);
80      }
81  
82      @Test
83      public void testBracketSin() {
84          double[] result = UnivariateSolverUtils.bracket(sin,
85                  0.0, -2.0, 2.0);
86          Assert.assertTrue(sin.value(result[0]) < 0);
87          Assert.assertTrue(sin.value(result[1]) > 0);
88      }
89  
90      @Test
91      public void testBracketCentered() {
92          double initial = 0.1;
93          double[] result = UnivariateSolverUtils.bracket(sin, initial, -2.0, 2.0, 0.2, 1.0, 100);
94          Assert.assertTrue(result[0] < initial);
95          Assert.assertTrue(result[1] > initial);
96          Assert.assertTrue(sin.value(result[0]) < 0);
97          Assert.assertTrue(sin.value(result[1]) > 0);
98      }
99  
100     @Test
101     public void testBracketLow() {
102         double initial = 0.5;
103         double[] result = UnivariateSolverUtils.bracket(sin, initial, -2.0, 2.0, 0.2, 1.0, 100);
104         Assert.assertTrue(result[0] < initial);
105         Assert.assertTrue(result[1] < initial);
106         Assert.assertTrue(sin.value(result[0]) < 0);
107         Assert.assertTrue(sin.value(result[1]) > 0);
108     }
109 
110     @Test
111     public void testBracketHigh(){
112         double initial = -0.5;
113         double[] result = UnivariateSolverUtils.bracket(sin, initial, -2.0, 2.0, 0.2, 1.0, 100);
114         Assert.assertTrue(result[0] > initial);
115         Assert.assertTrue(result[1] > initial);
116         Assert.assertTrue(sin.value(result[0]) < 0);
117         Assert.assertTrue(sin.value(result[1]) > 0);
118     }
119 
120     @Test(expected=NoBracketingException.class)
121     public void testBracketLinear(){
122         UnivariateSolverUtils.bracket(new UnivariateFunction() {
123             @Override
124             public double value(double x) {
125                 return 1 - x;
126             }
127         }, 1000, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0, 1.0, 100);
128     }
129 
130     @Test
131     public void testBracketExponential(){
132         double[] result = UnivariateSolverUtils.bracket(new UnivariateFunction() {
133             @Override
134             public double value(double x) {
135                 return 1 - x;
136             }
137         }, 1000, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0, 2.0, 10);
138         Assert.assertTrue(result[0] <= 1);
139         Assert.assertTrue(result[1] >= 1);
140     }
141 
142     @Test
143     public void testBracketEndpointRoot() {
144         double[] result = UnivariateSolverUtils.bracket(sin, 1.5, 0, 2.0);
145         Assert.assertEquals(0.0, sin.value(result[0]), 1.0e-15);
146         Assert.assertTrue(sin.value(result[1]) > 0);
147     }
148 
149     @Test(expected=NullArgumentException.class)
150     public void testNullFunction() {
151         UnivariateSolverUtils.bracket(null, 1.5, 0, 2.0);
152     }
153 
154     @Test(expected=MathIllegalArgumentException.class)
155     public void testBadInitial() {
156         UnivariateSolverUtils.bracket(sin, 2.5, 0, 2.0);
157     }
158 
159     @Test(expected=MathIllegalArgumentException.class)
160     public void testBadAdditive() {
161         UnivariateSolverUtils.bracket(sin, 1.0, -2.0, 3.0, -1.0, 1.0, 100);
162     }
163 
164     @Test(expected=NoBracketingException.class)
165     public void testIterationExceeded() {
166         UnivariateSolverUtils.bracket(sin, 1.0, -2.0, 3.0, 1.0e-5, 1.0, 100);
167     }
168 
169     @Test(expected=MathIllegalArgumentException.class)
170     public void testBadEndpoints() {
171         // endpoints not valid
172         UnivariateSolverUtils.bracket(sin, 1.5, 2.0, 1.0);
173     }
174 
175     @Test(expected=MathIllegalArgumentException.class)
176     public void testBadMaximumIterations() {
177         // bad maximum iterations
178         UnivariateSolverUtils.bracket(sin, 1.5, 0, 2.0, 0);
179     }
180 
181     /** check the search continues when a = lowerBound and b < upperBound. */
182     @Test
183     public void testBracketLoopConditionForB() {
184         double[] result = UnivariateSolverUtils.bracket(sin, -0.9, -1, 1, 0.1, 1, 100);
185         Assert.assertTrue(result[0] <= 0);
186         Assert.assertTrue(result[1] >= 0);
187     }
188 
189     @Test
190     public void testMisc() {
191         UnivariateFunction f = new QuinticFunction();
192         double result;
193         // Static solve method
194         result = UnivariateSolverUtils.solve(f, -0.2, 0.2);
195         Assert.assertEquals(result, 0, 1E-8);
196         result = UnivariateSolverUtils.solve(f, -0.1, 0.3);
197         Assert.assertEquals(result, 0, 1E-8);
198         result = UnivariateSolverUtils.solve(f, -0.3, 0.45);
199         Assert.assertEquals(result, 0, 1E-6);
200         result = UnivariateSolverUtils.solve(f, 0.3, 0.7);
201         Assert.assertEquals(result, 0.5, 1E-6);
202         result = UnivariateSolverUtils.solve(f, 0.2, 0.6);
203         Assert.assertEquals(result, 0.5, 1E-6);
204         result = UnivariateSolverUtils.solve(f, 0.05, 0.95);
205         Assert.assertEquals(result, 0.5, 1E-6);
206         result = UnivariateSolverUtils.solve(f, 0.85, 1.25);
207         Assert.assertEquals(result, 1.0, 1E-6);
208         result = UnivariateSolverUtils.solve(f, 0.8, 1.2);
209         Assert.assertEquals(result, 1.0, 1E-6);
210         result = UnivariateSolverUtils.solve(f, 0.85, 1.75);
211         Assert.assertEquals(result, 1.0, 1E-6);
212         result = UnivariateSolverUtils.solve(f, 0.55, 1.45);
213         Assert.assertEquals(result, 1.0, 1E-6);
214         result = UnivariateSolverUtils.solve(f, 0.85, 5);
215         Assert.assertEquals(result, 1.0, 1E-6);
216     }
217 }