1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.optim.nonlinear.scalar.noderiv;
24
25 import org.hipparchus.analysis.MultivariateFunction;
26 import org.hipparchus.analysis.MultivariateVectorFunction;
27 import org.hipparchus.exception.MathIllegalStateException;
28 import org.hipparchus.exception.MathRuntimeException;
29 import org.hipparchus.linear.Array2DRowRealMatrix;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.optim.InitialGuess;
32 import org.hipparchus.optim.MaxEval;
33 import org.hipparchus.optim.PointValuePair;
34 import org.hipparchus.optim.SimpleBounds;
35 import org.hipparchus.optim.nonlinear.scalar.GoalType;
36 import org.hipparchus.optim.nonlinear.scalar.LeastSquaresConverter;
37 import org.hipparchus.optim.nonlinear.scalar.ObjectiveFunction;
38 import org.hipparchus.util.FastMath;
39 import org.junit.jupiter.api.Test;
40
41 import static org.junit.jupiter.api.Assertions.assertEquals;
42 import static org.junit.jupiter.api.Assertions.assertThrows;
43 import static org.junit.jupiter.api.Assertions.assertTrue;
44
45 class SimplexOptimizerNelderMeadTest {
46 @Test
47 void testBoundsUnsupported() {
48 assertThrows(MathRuntimeException.class, () -> {
49 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
50 final FourExtrema fourExtrema = new FourExtrema();
51
52 optimizer.optimize(new MaxEval(100),
53 new ObjectiveFunction(fourExtrema),
54 GoalType.MINIMIZE,
55 new InitialGuess(new double[]{-3, 0}),
56 new NelderMeadSimplex(new double[]{0.2, 0.2}),
57 new SimpleBounds(new double[]{-5, -1},
58 new double[]{5, 1}));
59 });
60 }
61
62 @Test
63 void testMinimize1() {
64 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
65 final FourExtrema fourExtrema = new FourExtrema();
66
67 final PointValuePair optimum
68 = optimizer.optimize(new MaxEval(100),
69 new ObjectiveFunction(fourExtrema),
70 GoalType.MINIMIZE,
71 new InitialGuess(new double[] { -3, 0 }),
72 new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
73 assertEquals(fourExtrema.xM, optimum.getPoint()[0], 2e-7);
74 assertEquals(fourExtrema.yP, optimum.getPoint()[1], 2e-5);
75 assertEquals(fourExtrema.valueXmYp, optimum.getValue(), 6e-12);
76 assertTrue(optimizer.getEvaluations() > 60);
77 assertTrue(optimizer.getEvaluations() < 90);
78
79
80 assertTrue(optimizer.getIterations() > 0);
81 }
82
83 @Test
84 void testMinimize2() {
85 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
86 final FourExtrema fourExtrema = new FourExtrema();
87
88 final PointValuePair optimum
89 = optimizer.optimize(new MaxEval(100),
90 new ObjectiveFunction(fourExtrema),
91 GoalType.MINIMIZE,
92 new InitialGuess(new double[] { 1, 0 }),
93 new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
94 assertEquals(fourExtrema.xP, optimum.getPoint()[0], 5e-6);
95 assertEquals(fourExtrema.yM, optimum.getPoint()[1], 6e-6);
96 assertEquals(fourExtrema.valueXpYm, optimum.getValue(), 1e-11);
97 assertTrue(optimizer.getEvaluations() > 60);
98 assertTrue(optimizer.getEvaluations() < 90);
99
100
101 assertTrue(optimizer.getIterations() > 0);
102 }
103
104 @Test
105 void testMaximize1() {
106 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
107 final FourExtrema fourExtrema = new FourExtrema();
108
109 final PointValuePair optimum
110 = optimizer.optimize(new MaxEval(100),
111 new ObjectiveFunction(fourExtrema),
112 GoalType.MAXIMIZE,
113 new InitialGuess(new double[] { -3, 0 }),
114 new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
115 assertEquals(fourExtrema.xM, optimum.getPoint()[0], 1e-5);
116 assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-6);
117 assertEquals(fourExtrema.valueXmYm, optimum.getValue(), 3e-12);
118 assertTrue(optimizer.getEvaluations() > 60);
119 assertTrue(optimizer.getEvaluations() < 90);
120
121
122 assertTrue(optimizer.getIterations() > 0);
123 }
124
125 @Test
126 void testMaximize2() {
127 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
128 final FourExtrema fourExtrema = new FourExtrema();
129
130 final PointValuePair optimum
131 = optimizer.optimize(new MaxEval(100),
132 new ObjectiveFunction(fourExtrema),
133 GoalType.MAXIMIZE,
134 new InitialGuess(new double[] { 1, 0 }),
135 new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
136 assertEquals(fourExtrema.xP, optimum.getPoint()[0], 4e-6);
137 assertEquals(fourExtrema.yP, optimum.getPoint()[1], 5e-6);
138 assertEquals(fourExtrema.valueXpYp, optimum.getValue(), 7e-12);
139 assertTrue(optimizer.getEvaluations() > 60);
140 assertTrue(optimizer.getEvaluations() < 90);
141
142
143 assertTrue(optimizer.getIterations() > 0);
144 }
145
146 @Test
147 void testRosenbrock() {
148
149 Rosenbrock rosenbrock = new Rosenbrock();
150 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-3);
151 PointValuePair optimum
152 = optimizer.optimize(new MaxEval(100),
153 new ObjectiveFunction(rosenbrock),
154 GoalType.MINIMIZE,
155 new InitialGuess(new double[] { -1.2, 1 }),
156 new NelderMeadSimplex(new double[][] {
157 { -1.2, 1 },
158 { 0.9, 1.2 },
159 { 3.5, -2.3 } }));
160
161 assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
162 assertTrue(optimizer.getEvaluations() > 40);
163 assertTrue(optimizer.getEvaluations() < 50);
164 assertTrue(optimum.getValue() < 8e-4);
165 }
166
167 @Test
168 void testPowell() {
169 Powell powell = new Powell();
170 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-3);
171 PointValuePair optimum =
172 optimizer.optimize(new MaxEval(200),
173 new ObjectiveFunction(powell),
174 GoalType.MINIMIZE,
175 new InitialGuess(new double[] { 3, -1, 0, 1 }),
176 new NelderMeadSimplex(4));
177 assertEquals(powell.getCount(), optimizer.getEvaluations());
178 assertTrue(optimizer.getEvaluations() > 110);
179 assertTrue(optimizer.getEvaluations() < 130);
180 assertTrue(optimum.getValue() < 2e-3);
181 }
182
183 @Test
184 void testLeastSquares1() {
185 final RealMatrix factors
186 = new Array2DRowRealMatrix(new double[][] {
187 { 1, 0 },
188 { 0, 1 }
189 }, false);
190 LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorFunction() {
191 public double[] value(double[] variables) {
192 return factors.operate(variables);
193 }
194 }, new double[] { 2.0, -3.0 });
195 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-6);
196 PointValuePair optimum =
197 optimizer.optimize(new MaxEval(200),
198 new ObjectiveFunction(ls),
199 GoalType.MINIMIZE,
200 new InitialGuess(new double[] { 10, 10 }),
201 new NelderMeadSimplex(2));
202 assertEquals( 2, optimum.getPointRef()[0], 3e-5);
203 assertEquals(-3, optimum.getPointRef()[1], 4e-4);
204 assertTrue(optimizer.getEvaluations() > 60);
205 assertTrue(optimizer.getEvaluations() < 80);
206 assertTrue(optimum.getValue() < 1.0e-6);
207 }
208
209 @Test
210 void testLeastSquares2() {
211 final RealMatrix factors
212 = new Array2DRowRealMatrix(new double[][] {
213 { 1, 0 },
214 { 0, 1 }
215 }, false);
216 LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorFunction() {
217 public double[] value(double[] variables) {
218 return factors.operate(variables);
219 }
220 }, new double[] { 2, -3 }, new double[] { 10, 0.1 });
221 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-6);
222 PointValuePair optimum =
223 optimizer.optimize(new MaxEval(200),
224 new ObjectiveFunction(ls),
225 GoalType.MINIMIZE,
226 new InitialGuess(new double[] { 10, 10 }),
227 new NelderMeadSimplex(2));
228 assertEquals( 2, optimum.getPointRef()[0], 5e-5);
229 assertEquals(-3, optimum.getPointRef()[1], 8e-4);
230 assertTrue(optimizer.getEvaluations() > 60);
231 assertTrue(optimizer.getEvaluations() < 80);
232 assertTrue(optimum.getValue() < 1e-6);
233 }
234
235 @Test
236 void testLeastSquares3() {
237 final RealMatrix factors =
238 new Array2DRowRealMatrix(new double[][] {
239 { 1, 0 },
240 { 0, 1 }
241 }, false);
242 LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorFunction() {
243 public double[] value(double[] variables) {
244 return factors.operate(variables);
245 }
246 }, new double[] { 2, -3 }, new Array2DRowRealMatrix(new double [][] {
247 { 1, 1.2 }, { 1.2, 2 }
248 }));
249 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-6);
250 PointValuePair optimum
251 = optimizer.optimize(new MaxEval(200),
252 new ObjectiveFunction(ls),
253 GoalType.MINIMIZE,
254 new InitialGuess(new double[] { 10, 10 }),
255 new NelderMeadSimplex(2));
256 assertEquals( 2, optimum.getPointRef()[0], 2e-3);
257 assertEquals(-3, optimum.getPointRef()[1], 8e-4);
258 assertTrue(optimizer.getEvaluations() > 60);
259 assertTrue(optimizer.getEvaluations() < 80);
260 assertTrue(optimum.getValue() < 1e-6);
261 }
262
263 @Test
264 void testMaxIterations() {
265 assertThrows(MathIllegalStateException.class, () -> {
266 Powell powell = new Powell();
267 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-3);
268 optimizer.optimize(new MaxEval(20),
269 new ObjectiveFunction(powell),
270 GoalType.MINIMIZE,
271 new InitialGuess(new double[]{3, -1, 0, 1}),
272 new NelderMeadSimplex(4));
273 });
274 }
275
276 private static class FourExtrema implements MultivariateFunction {
277
278 final double xM = -3.841947088256863675365;
279 final double yM = -1.391745200270734924416;
280 final double xP = 0.2286682237349059125691;
281 final double yP = -yM;
282 final double valueXmYm = 0.2373295333134216789769;
283 final double valueXmYp = -valueXmYm;
284 final double valueXpYm = -0.7290400707055187115322;
285 final double valueXpYp = -valueXpYm;
286
287 public double value(double[] variables) {
288 final double x = variables[0];
289 final double y = variables[1];
290 return (x == 0 || y == 0) ? 0 :
291 FastMath.atan(x) * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y) / (x * y);
292 }
293 }
294
295 private static class Rosenbrock implements MultivariateFunction {
296 private int count;
297
298 public Rosenbrock() {
299 count = 0;
300 }
301
302 public double value(double[] x) {
303 ++count;
304 double a = x[1] - x[0] * x[0];
305 double b = 1.0 - x[0];
306 return 100 * a * a + b * b;
307 }
308
309 public int getCount() {
310 return count;
311 }
312 }
313
314 private static class Powell implements MultivariateFunction {
315 private int count;
316
317 public Powell() {
318 count = 0;
319 }
320
321 public double value(double[] x) {
322 ++count;
323 double a = x[0] + 10 * x[1];
324 double b = x[2] - x[3];
325 double c = x[1] - 2 * x[2];
326 double d = x[0] - x[3];
327 return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
328 }
329
330 public int getCount() {
331 return count;
332 }
333 }
334 }