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.exception.MathRuntimeException;
27 import org.hipparchus.optim.InitialGuess;
28 import org.hipparchus.optim.MaxEval;
29 import org.hipparchus.optim.PointValuePair;
30 import org.hipparchus.optim.SimpleBounds;
31 import org.hipparchus.optim.SimpleValueChecker;
32 import org.hipparchus.optim.nonlinear.scalar.GoalType;
33 import org.hipparchus.optim.nonlinear.scalar.ObjectiveFunction;
34 import org.hipparchus.util.FastMath;
35 import org.junit.jupiter.api.Test;
36
37 import static org.junit.jupiter.api.Assertions.assertEquals;
38 import static org.junit.jupiter.api.Assertions.assertThrows;
39 import static org.junit.jupiter.api.Assertions.assertTrue;
40
41 class SimplexOptimizerMultiDirectionalTest {
42 @Test
43 void testBoundsUnsupported() {
44 assertThrows(MathRuntimeException.class, () -> {
45 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
46 final FourExtrema fourExtrema = new FourExtrema();
47
48 optimizer.optimize(new MaxEval(100),
49 new ObjectiveFunction(fourExtrema),
50 GoalType.MINIMIZE,
51 new InitialGuess(new double[]{-3, 0}),
52 new NelderMeadSimplex(new double[]{0.2, 0.2}),
53 new SimpleBounds(new double[]{-5, -1},
54 new double[]{5, 1}));
55 });
56 }
57
58 @Test
59 void testMinimize1() {
60 SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
61 final FourExtrema fourExtrema = new FourExtrema();
62
63 final PointValuePair optimum
64 = optimizer.optimize(new MaxEval(200),
65 new ObjectiveFunction(fourExtrema),
66 GoalType.MINIMIZE,
67 new InitialGuess(new double[] { -3, 0 }),
68 new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
69 assertEquals(fourExtrema.xM, optimum.getPoint()[0], 4e-6);
70 assertEquals(fourExtrema.yP, optimum.getPoint()[1], 3e-6);
71 assertEquals(fourExtrema.valueXmYp, optimum.getValue(), 8e-13);
72 assertTrue(optimizer.getEvaluations() > 120);
73 assertTrue(optimizer.getEvaluations() < 150);
74
75
76 assertTrue(optimizer.getIterations() > 0);
77 }
78
79 @Test
80 void testMinimize2() {
81 SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
82 final FourExtrema fourExtrema = new FourExtrema();
83
84 final PointValuePair optimum
85 = optimizer.optimize(new MaxEval(200),
86 new ObjectiveFunction(fourExtrema),
87 GoalType.MINIMIZE,
88 new InitialGuess(new double[] { 1, 0 }),
89 new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
90 assertEquals(fourExtrema.xP, optimum.getPoint()[0], 2e-8);
91 assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-6);
92 assertEquals(fourExtrema.valueXpYm, optimum.getValue(), 2e-12);
93 assertTrue(optimizer.getEvaluations() > 120);
94 assertTrue(optimizer.getEvaluations() < 150);
95
96
97 assertTrue(optimizer.getIterations() > 0);
98 }
99
100 @Test
101 void testMaximize1() {
102 SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
103 final FourExtrema fourExtrema = new FourExtrema();
104
105 final PointValuePair optimum
106 = optimizer.optimize(new MaxEval(200),
107 new ObjectiveFunction(fourExtrema),
108 GoalType.MAXIMIZE,
109 new InitialGuess(new double[] { -3.0, 0.0 }),
110 new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
111 assertEquals(fourExtrema.xM, optimum.getPoint()[0], 7e-7);
112 assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-7);
113 assertEquals(fourExtrema.valueXmYm, optimum.getValue(), 2e-14);
114 assertTrue(optimizer.getEvaluations() > 120);
115 assertTrue(optimizer.getEvaluations() < 150);
116
117
118 assertTrue(optimizer.getIterations() > 0);
119 }
120
121 @Test
122 void testMaximize2() {
123 SimplexOptimizer optimizer = new SimplexOptimizer(new SimpleValueChecker(1e-15, 1e-30));
124 final FourExtrema fourExtrema = new FourExtrema();
125
126 final PointValuePair optimum
127 = optimizer.optimize(new MaxEval(200),
128 new ObjectiveFunction(fourExtrema),
129 GoalType.MAXIMIZE,
130 new InitialGuess(new double[] { 1, 0 }),
131 new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
132 assertEquals(fourExtrema.xP, optimum.getPoint()[0], 2e-8);
133 assertEquals(fourExtrema.yP, optimum.getPoint()[1], 3e-6);
134 assertEquals(fourExtrema.valueXpYp, optimum.getValue(), 2e-12);
135 assertTrue(optimizer.getEvaluations() > 180);
136 assertTrue(optimizer.getEvaluations() < 220);
137
138
139 assertTrue(optimizer.getIterations() > 0);
140 }
141
142 @Test
143 void testRosenbrock() {
144 MultivariateFunction rosenbrock
145 = new MultivariateFunction() {
146 public double value(double[] x) {
147 ++count;
148 double a = x[1] - x[0] * x[0];
149 double b = 1.0 - x[0];
150 return 100 * a * a + b * b;
151 }
152 };
153
154 count = 0;
155 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-3);
156 PointValuePair optimum
157 = optimizer.optimize(new MaxEval(100),
158 new ObjectiveFunction(rosenbrock),
159 GoalType.MINIMIZE,
160 new InitialGuess(new double[] { -1.2, 1 }),
161 new MultiDirectionalSimplex(new double[][] {
162 { -1.2, 1.0 },
163 { 0.9, 1.2 },
164 { 3.5, -2.3 } }));
165
166 assertEquals(count, optimizer.getEvaluations());
167 assertTrue(optimizer.getEvaluations() > 50);
168 assertTrue(optimizer.getEvaluations() < 100);
169 assertTrue(optimum.getValue() > 1e-2);
170 }
171
172 @Test
173 void testPowell() {
174 MultivariateFunction powell
175 = new MultivariateFunction() {
176 public double value(double[] x) {
177 ++count;
178 double a = x[0] + 10 * x[1];
179 double b = x[2] - x[3];
180 double c = x[1] - 2 * x[2];
181 double d = x[0] - x[3];
182 return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
183 }
184 };
185
186 count = 0;
187 SimplexOptimizer optimizer = new SimplexOptimizer(-1, 1e-3);
188 PointValuePair optimum
189 = optimizer.optimize(new MaxEval(1000),
190 new ObjectiveFunction(powell),
191 GoalType.MINIMIZE,
192 new InitialGuess(new double[] { 3, -1, 0, 1 }),
193 new MultiDirectionalSimplex(4));
194 assertEquals(count, optimizer.getEvaluations());
195 assertTrue(optimizer.getEvaluations() > 800);
196 assertTrue(optimizer.getEvaluations() < 900);
197 assertTrue(optimum.getValue() > 1e-2);
198 }
199
200 @Test
201 void testMath283() {
202
203
204 SimplexOptimizer optimizer = new SimplexOptimizer(1e-14, 1e-14);
205 final Gaussian2D function = new Gaussian2D(0, 0, 1);
206 PointValuePair estimate = optimizer.optimize(new MaxEval(1000),
207 new ObjectiveFunction(function),
208 GoalType.MAXIMIZE,
209 new InitialGuess(function.getMaximumPosition()),
210 new MultiDirectionalSimplex(2));
211 final double EPSILON = 1e-5;
212 final double expectedMaximum = function.getMaximum();
213 final double actualMaximum = estimate.getValue();
214 assertEquals(expectedMaximum, actualMaximum, EPSILON);
215
216 final double[] expectedPosition = function.getMaximumPosition();
217 final double[] actualPosition = estimate.getPoint();
218 assertEquals(expectedPosition[0], actualPosition[0], EPSILON );
219 assertEquals(expectedPosition[1], actualPosition[1], EPSILON );
220 }
221
222 private static class FourExtrema implements MultivariateFunction {
223
224 final double xM = -3.841947088256863675365;
225 final double yM = -1.391745200270734924416;
226 final double xP = 0.2286682237349059125691;
227 final double yP = -yM;
228 final double valueXmYm = 0.2373295333134216789769;
229 final double valueXmYp = -valueXmYm;
230 final double valueXpYm = -0.7290400707055187115322;
231 final double valueXpYp = -valueXpYm;
232
233 public double value(double[] variables) {
234 final double x = variables[0];
235 final double y = variables[1];
236 return (x == 0 || y == 0) ? 0 :
237 FastMath.atan(x) * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y) / (x * y);
238 }
239 }
240
241 private static class Gaussian2D implements MultivariateFunction {
242 private final double[] maximumPosition;
243 private final double std;
244
245 public Gaussian2D(double xOpt, double yOpt, double std) {
246 maximumPosition = new double[] { xOpt, yOpt };
247 this.std = std;
248 }
249
250 public double getMaximum() {
251 return value(maximumPosition);
252 }
253
254 public double[] getMaximumPosition() {
255 return maximumPosition.clone();
256 }
257
258 public double value(double[] point) {
259 final double x = point[0], y = point[1];
260 final double twoS2 = 2.0 * std * std;
261 return 1.0 / (twoS2 * FastMath.PI) * FastMath.exp(-(x * x + y * y) / twoS2);
262 }
263 }
264
265 private int count;
266 }