1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.optim.univariate;
18
19
20 import org.apache.commons.math4.legacy.analysis.FunctionUtils;
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.function.Sin;
24 import org.apache.commons.math4.legacy.analysis.function.StepFunction;
25 import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
26 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
27 import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
28 import org.apache.commons.math4.legacy.optim.ConvergenceChecker;
29 import org.apache.commons.math4.legacy.optim.MaxEval;
30 import org.apache.commons.math4.legacy.optim.nonlinear.scalar.GoalType;
31 import org.apache.commons.math4.legacy.stat.descriptive.DescriptiveStatistics;
32 import org.apache.commons.math4.core.jdkmath.JdkMath;
33 import org.junit.Assert;
34 import org.junit.Test;
35
36
37
38 public final class BrentOptimizerTest {
39
40 @Test
41 public void testSinMin() {
42 UnivariateFunction f = new Sin();
43 UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-14);
44 Assert.assertEquals(3 * Math.PI / 2, optimizer.optimize(new MaxEval(200),
45 new UnivariateObjectiveFunction(f),
46 GoalType.MINIMIZE,
47 new SearchInterval(4, 5)).getPoint(), 1e-8);
48 Assert.assertTrue(optimizer.getEvaluations() <= 50);
49 Assert.assertEquals(200, optimizer.getMaxEvaluations());
50 Assert.assertEquals(3 * Math.PI / 2, optimizer.optimize(new MaxEval(200),
51 new UnivariateObjectiveFunction(f),
52 GoalType.MINIMIZE,
53 new SearchInterval(1, 5)).getPoint(), 1e-8);
54 Assert.assertTrue(optimizer.getEvaluations() <= 100);
55 Assert.assertTrue(optimizer.getEvaluations() >= 15);
56 try {
57 optimizer.optimize(new MaxEval(10),
58 new UnivariateObjectiveFunction(f),
59 GoalType.MINIMIZE,
60 new SearchInterval(4, 5));
61 Assert.fail("an exception should have been thrown");
62 } catch (TooManyEvaluationsException fee) {
63
64 }
65 }
66
67 @Test
68 public void testSinMinWithValueChecker() {
69 final UnivariateFunction f = new Sin();
70 final ConvergenceChecker<UnivariatePointValuePair> checker = new SimpleUnivariateValueChecker(1e-5, 1e-14);
71
72
73
74 final UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-14, checker);
75 final UnivariatePointValuePair result = optimizer.optimize(new MaxEval(200),
76 new UnivariateObjectiveFunction(f),
77 GoalType.MINIMIZE,
78 new SearchInterval(4, 5));
79 Assert.assertEquals(3 * Math.PI / 2, result.getPoint(), 1e-3);
80 }
81
82 @Test
83 public void testBoundaries() {
84 final double lower = -1.0;
85 final double upper = +1.0;
86 UnivariateFunction f = new UnivariateFunction() {
87 @Override
88 public double value(double x) {
89 if (x < lower) {
90 throw new NumberIsTooSmallException(x, lower, true);
91 } else if (x > upper) {
92 throw new NumberIsTooLargeException(x, upper, true);
93 } else {
94 return x;
95 }
96 }
97 };
98 UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-14);
99 Assert.assertEquals(lower,
100 optimizer.optimize(new MaxEval(100),
101 new UnivariateObjectiveFunction(f),
102 GoalType.MINIMIZE,
103 new SearchInterval(lower, upper)).getPoint(),
104 1.0e-8);
105 Assert.assertEquals(upper,
106 optimizer.optimize(new MaxEval(100),
107 new UnivariateObjectiveFunction(f),
108 GoalType.MAXIMIZE,
109 new SearchInterval(lower, upper)).getPoint(),
110 1.0e-8);
111 }
112
113 @Test
114 public void testQuinticMin() {
115
116 UnivariateFunction f = new QuinticFunction();
117 UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-14);
118 Assert.assertEquals(-0.27195613, optimizer.optimize(new MaxEval(200),
119 new UnivariateObjectiveFunction(f),
120 GoalType.MINIMIZE,
121 new SearchInterval(-0.3, -0.2)).getPoint(), 1.0e-8);
122 Assert.assertEquals( 0.82221643, optimizer.optimize(new MaxEval(200),
123 new UnivariateObjectiveFunction(f),
124 GoalType.MINIMIZE,
125 new SearchInterval(0.3, 0.9)).getPoint(), 1.0e-8);
126 Assert.assertTrue(optimizer.getEvaluations() <= 50);
127
128
129 Assert.assertEquals(-0.27195613, optimizer.optimize(new MaxEval(200),
130 new UnivariateObjectiveFunction(f),
131 GoalType.MINIMIZE,
132 new SearchInterval(-1.0, 0.2)).getPoint(), 1.0e-8);
133 Assert.assertTrue(optimizer.getEvaluations() <= 50);
134 }
135
136 @Test
137 public void testQuinticMinStatistics() {
138
139 UnivariateFunction f = new QuinticFunction();
140 UnivariateOptimizer optimizer = new BrentOptimizer(1e-11, 1e-14);
141
142 final DescriptiveStatistics[] stat = new DescriptiveStatistics[2];
143 for (int i = 0; i < stat.length; i++) {
144 stat[i] = new DescriptiveStatistics();
145 }
146
147 final double min = -0.75;
148 final double max = 0.25;
149 final int nSamples = 200;
150 final double delta = (max - min) / nSamples;
151 for (int i = 0; i < nSamples; i++) {
152 final double start = min + i * delta;
153 stat[0].addValue(optimizer.optimize(new MaxEval(40),
154 new UnivariateObjectiveFunction(f),
155 GoalType.MINIMIZE,
156 new SearchInterval(min, max, start)).getPoint());
157 stat[1].addValue(optimizer.getEvaluations());
158 }
159
160 final double meanOptValue = stat[0].getMean();
161 final double medianEval = stat[1].getPercentile(50);
162 Assert.assertTrue(meanOptValue > -0.2719561281);
163 Assert.assertTrue(meanOptValue < -0.2719561280);
164 Assert.assertEquals(23, (int) medianEval);
165
166
167 Assert.assertTrue(optimizer.getIterations() > 0);
168 }
169
170 @Test
171 public void testQuinticMax() {
172
173
174 UnivariateFunction f = new QuinticFunction();
175 UnivariateOptimizer optimizer = new BrentOptimizer(1e-12, 1e-14);
176 Assert.assertEquals(0.27195613, optimizer.optimize(new MaxEval(100),
177 new UnivariateObjectiveFunction(f),
178 GoalType.MAXIMIZE,
179 new SearchInterval(0.2, 0.3)).getPoint(), 1e-8);
180 try {
181 optimizer.optimize(new MaxEval(5),
182 new UnivariateObjectiveFunction(f),
183 GoalType.MAXIMIZE,
184 new SearchInterval(0.2, 0.3));
185 Assert.fail("an exception should have been thrown");
186 } catch (TooManyEvaluationsException miee) {
187
188 }
189 }
190
191 @Test
192 public void testMinEndpoints() {
193 UnivariateFunction f = new Sin();
194 UnivariateOptimizer optimizer = new BrentOptimizer(1e-8, 1e-14);
195
196
197 double result = optimizer.optimize(new MaxEval(50),
198 new UnivariateObjectiveFunction(f),
199 GoalType.MINIMIZE,
200 new SearchInterval(3 * Math.PI / 2, 5)).getPoint();
201 Assert.assertEquals(3 * Math.PI / 2, result, 1e-6);
202
203 result = optimizer.optimize(new MaxEval(50),
204 new UnivariateObjectiveFunction(f),
205 GoalType.MINIMIZE,
206 new SearchInterval(4, 3 * Math.PI / 2)).getPoint();
207 Assert.assertEquals(3 * Math.PI / 2, result, 1e-6);
208 }
209
210 @Test
211 public void testMath832() {
212 final UnivariateFunction f = new UnivariateFunction() {
213 @Override
214 public double value(double x) {
215 final double sqrtX = JdkMath.sqrt(x);
216 final double a = 1e2 * sqrtX;
217 final double b = 1e6 / x;
218 final double c = 1e4 / sqrtX;
219
220 return a + b + c;
221 }
222 };
223
224 UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-8);
225 final double result = optimizer.optimize(new MaxEval(1484),
226 new UnivariateObjectiveFunction(f),
227 GoalType.MINIMIZE,
228 new SearchInterval(Double.MIN_VALUE,
229 Double.MAX_VALUE)).getPoint();
230
231 Assert.assertEquals(804.9355825, result, 1e-6);
232 }
233
234
235
236
237
238
239 @Test
240 public void testKeepInitIfBest() {
241 final double minSin = 3 * Math.PI / 2;
242 final double offset = 1e-8;
243 final double delta = 1e-7;
244 final UnivariateFunction f1 = new Sin();
245 final UnivariateFunction f2 = new StepFunction(new double[] { minSin, minSin + offset, minSin + 2 * offset},
246 new double[] { 0, -1, 0 });
247 final UnivariateFunction f = FunctionUtils.add(f1, f2);
248
249
250 final double relTol = 1e-8;
251 final UnivariateOptimizer optimizer = new BrentOptimizer(relTol, 1e-100);
252 final double init = minSin + 1.5 * offset;
253 final UnivariatePointValuePair result
254 = optimizer.optimize(new MaxEval(200),
255 new UnivariateObjectiveFunction(f),
256 GoalType.MINIMIZE,
257 new SearchInterval(minSin - 6.789 * delta,
258 minSin + 9.876 * delta,
259 init));
260
261 final double sol = result.getPoint();
262 final double expected = init;
263
264
265
266
267
268
269 Assert.assertTrue("Best point not reported", f.value(sol) <= f.value(expected));
270 }
271
272
273
274
275
276
277 @Test
278 public void testMath855() {
279 final double minSin = 3 * Math.PI / 2;
280 final double offset = 1e-8;
281 final double delta = 1e-7;
282 final UnivariateFunction f1 = new Sin();
283 final UnivariateFunction f2 = new StepFunction(new double[] { minSin, minSin + offset, minSin + 5 * offset },
284 new double[] { 0, -1, 0 });
285 final UnivariateFunction f = FunctionUtils.add(f1, f2);
286 final UnivariateOptimizer optimizer = new BrentOptimizer(1e-8, 1e-100);
287 final UnivariatePointValuePair result
288 = optimizer.optimize(new MaxEval(200),
289 new UnivariateObjectiveFunction(f),
290 GoalType.MINIMIZE,
291 new SearchInterval(minSin - 6.789 * delta,
292 minSin + 9.876 * delta));
293
294 final double sol = result.getPoint();
295 final double expected = 4.712389027602411;
296
297
298
299
300
301 Assert.assertTrue("Best point not reported", f.value(sol) <= f.value(expected));
302 }
303 }