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 }