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