1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.apache.commons.math4.legacy.analysis.solvers;
18  
19  import org.apache.commons.math4.legacy.analysis.FunctionUtils;
20  import org.apache.commons.math4.legacy.analysis.MonitoredFunction;
21  import org.apache.commons.math4.legacy.analysis.QuinticFunction;
22  import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
23  import org.apache.commons.math4.legacy.analysis.differentiation.DerivativeStructure;
24  import org.apache.commons.math4.legacy.analysis.differentiation.UnivariateDifferentiableFunction;
25  import org.apache.commons.math4.legacy.analysis.function.Constant;
26  import org.apache.commons.math4.legacy.analysis.function.Inverse;
27  import org.apache.commons.math4.legacy.analysis.function.Sin;
28  import org.apache.commons.math4.legacy.analysis.function.Sqrt;
29  import org.apache.commons.math4.legacy.exception.NoBracketingException;
30  import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
31  import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
32  import org.apache.commons.math4.core.jdkmath.JdkMath;
33  import org.junit.Assert;
34  import org.junit.Test;
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  public final class BrentSolverTest {
47      @Test
48      public void testSinZero() {
49          
50          
51          
52          UnivariateFunction f = new Sin();
53          double result;
54          UnivariateSolver solver = new BrentSolver();
55          
56          result = solver.solve(100, f, 3, 4);
57          
58          
59          Assert.assertEquals(result, JdkMath.PI, solver.getAbsoluteAccuracy());
60          Assert.assertTrue(solver.getEvaluations() <= 7);
61          
62          result = solver.solve(100, f, 1, 4);
63          
64          
65          Assert.assertEquals(result, JdkMath.PI, solver.getAbsoluteAccuracy());
66          Assert.assertTrue(solver.getEvaluations() <= 8);
67      }
68  
69      @Test
70      public void testQuinticZero() {
71          
72          
73          
74          
75          
76          
77          
78          UnivariateFunction f = new QuinticFunction();
79          double result;
80          
81          UnivariateSolver solver = new BrentSolver();
82          
83          
84          result = solver.solve(100, f, -0.2, 0.2);
85          
86          
87          Assert.assertEquals(result, 0, solver.getAbsoluteAccuracy());
88          Assert.assertTrue(solver.getEvaluations() <= 3);
89          
90          
91          result = solver.solve(100, f, -0.1, 0.3);
92          
93          
94          Assert.assertEquals(result, 0, solver.getAbsoluteAccuracy());
95          
96          Assert.assertTrue(solver.getEvaluations() <= 7);
97          
98          result = solver.solve(100, f, -0.3, 0.45);
99          
100         
101         Assert.assertEquals(result, 0, solver.getAbsoluteAccuracy());
102         
103         Assert.assertTrue(solver.getEvaluations() <= 8);
104         
105         result = solver.solve(100, f, 0.3, 0.7);
106         
107         
108         Assert.assertEquals(result, 0.5, solver.getAbsoluteAccuracy());
109         
110         Assert.assertTrue(solver.getEvaluations() <= 9);
111         
112         result = solver.solve(100, f, 0.2, 0.6);
113         
114         
115         Assert.assertEquals(result, 0.5, solver.getAbsoluteAccuracy());
116         Assert.assertTrue(solver.getEvaluations() <= 10);
117         
118         result = solver.solve(100, f, 0.05, 0.95);
119         
120         
121         Assert.assertEquals(result, 0.5, solver.getAbsoluteAccuracy());
122         Assert.assertTrue(solver.getEvaluations() <= 11);
123         
124         
125         result = solver.solve(100, f, 0.85, 1.25);
126         
127         
128         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
129         Assert.assertTrue(solver.getEvaluations() <= 11);
130         
131         result = solver.solve(100, f, 0.8, 1.2);
132         
133         
134         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
135         Assert.assertTrue(solver.getEvaluations() <= 11);
136         
137         result = solver.solve(100, f, 0.85, 1.75);
138         
139         
140         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
141         Assert.assertTrue(solver.getEvaluations() <= 13);
142         
143         result = solver.solve(100, f, 0.55, 1.45);
144         
145         
146         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
147         Assert.assertTrue(solver.getEvaluations() <= 10);
148         
149         result = solver.solve(100, f, 0.85, 5);
150         
151        
152         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
153         Assert.assertTrue(solver.getEvaluations() <= 15);
154 
155         try {
156             result = solver.solve(5, f, 0.85, 5);
157             Assert.fail("Expected TooManyEvaluationsException");
158         } catch (TooManyEvaluationsException e) {
159             
160         }
161     }
162 
163     @Test
164     public void testRootEndpoints() {
165         UnivariateFunction f = new Sin();
166         BrentSolver solver = new BrentSolver();
167 
168         
169         double result = solver.solve(100, f, JdkMath.PI, 4);
170         Assert.assertEquals(JdkMath.PI, result, solver.getAbsoluteAccuracy());
171 
172         result = solver.solve(100, f, 3, JdkMath.PI);
173         Assert.assertEquals(JdkMath.PI, result, solver.getAbsoluteAccuracy());
174 
175         result = solver.solve(100, f, JdkMath.PI, 4, 3.5);
176         Assert.assertEquals(JdkMath.PI, result, solver.getAbsoluteAccuracy());
177 
178         result = solver.solve(100, f, 3, JdkMath.PI, 3.07);
179         Assert.assertEquals(JdkMath.PI, result, solver.getAbsoluteAccuracy());
180     }
181 
182     @Test
183     public void testBadEndpoints() {
184         UnivariateFunction f = new Sin();
185         BrentSolver solver = new BrentSolver();
186         try {  
187             solver.solve(100, f, 1, -1);
188             Assert.fail("Expecting NumberIsTooLargeException - bad interval");
189         } catch (NumberIsTooLargeException ex) {
190             
191         }
192         try {  
193             solver.solve(100, f, 1, 1.5);
194             Assert.fail("Expecting NoBracketingException - non-bracketing");
195         } catch (NoBracketingException ex) {
196             
197         }
198         try {  
199             solver.solve(100, f, 1, 1.5, 1.2);
200             Assert.fail("Expecting NoBracketingException - non-bracketing");
201         } catch (NoBracketingException ex) {
202             
203         }
204     }
205 
206     @Test
207     public void testInitialGuess() {
208         MonitoredFunction f = new MonitoredFunction(new QuinticFunction());
209         BrentSolver solver = new BrentSolver();
210         double result;
211 
212         
213         result = solver.solve(100, f, 0.6, 7.0);
214         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
215         int referenceCallsCount = f.getCallsCount();
216         Assert.assertTrue(referenceCallsCount >= 13);
217 
218         
219         try {
220           result = solver.solve(100, f, 0.6, 7.0, 0.0);
221           Assert.fail("a NumberIsTooLargeException was expected");
222         } catch (NumberIsTooLargeException iae) {
223             
224         }
225 
226         
227         f.setCallsCount(0);
228         result = solver.solve(100, f, 0.6, 7.0, 0.61);
229         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
230         Assert.assertTrue(f.getCallsCount() > referenceCallsCount);
231 
232         
233         f.setCallsCount(0);
234         result = solver.solve(100, f, 0.6, 7.0, 0.999999);
235         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
236         Assert.assertTrue(f.getCallsCount() < referenceCallsCount);
237 
238         
239         f.setCallsCount(0);
240         result = solver.solve(100, f, 0.6, 7.0, 1.0);
241         Assert.assertEquals(result, 1.0, solver.getAbsoluteAccuracy());
242         Assert.assertEquals(1, solver.getEvaluations());
243         Assert.assertEquals(1, f.getCallsCount());
244     }
245 
246     @Test
247     public void testMath832() {
248         final UnivariateFunction f = new UnivariateFunction() {
249                 private final UnivariateDifferentiableFunction sqrt = new Sqrt();
250                 private final UnivariateDifferentiableFunction inv = new Inverse();
251                 private final UnivariateDifferentiableFunction func
252                     = FunctionUtils.add(FunctionUtils.multiply(new Constant(1e2), sqrt),
253                                         FunctionUtils.multiply(new Constant(1e6), inv),
254                                         FunctionUtils.multiply(new Constant(1e4),
255                                                                FunctionUtils.compose(inv, sqrt)));
256 
257                 @Override
258                 public double value(double x) {
259                     return func.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
260                 }
261             };
262 
263         BrentSolver solver = new BrentSolver();
264         final double result = solver.solve(100, f, 1, 1e30, 1 + 1e-10);
265         Assert.assertEquals(804.93558250, result, solver.getAbsoluteAccuracy());
266     }
267 }