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