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.nonlinear.scalar.noderiv;
23
24 import org.hipparchus.analysis.MultivariateFunction;
25 import org.hipparchus.analysis.SumSincFunction;
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.nonlinear.scalar.GoalType;
32 import org.hipparchus.optim.nonlinear.scalar.ObjectiveFunction;
33 import org.hipparchus.util.FastMath;
34 import org.junit.jupiter.api.Test;
35
36 import static org.junit.jupiter.api.Assertions.assertEquals;
37 import static org.junit.jupiter.api.Assertions.assertThrows;
38 import static org.junit.jupiter.api.Assertions.assertTrue;
39
40
41
42
43 class PowellOptimizerTest {
44 @Test
45 void testBoundsUnsupported() {
46 assertThrows(MathRuntimeException.class, () -> {
47 final MultivariateFunction func = new SumSincFunction(-1);
48 final PowellOptimizer optim = new PowellOptimizer(1e-8, 1e-5,
49 1e-4, 1e-4);
50
51 optim.optimize(new MaxEval(100),
52 new ObjectiveFunction(func),
53 GoalType.MINIMIZE,
54 new InitialGuess(new double[]{-3, 0}),
55 new SimpleBounds(new double[]{-5, -1},
56 new double[]{5, 1}));
57 });
58 }
59
60 @Test
61 void testSumSinc() {
62 final MultivariateFunction func = new SumSincFunction(-1);
63
64 int dim = 2;
65 final double[] minPoint = new double[dim];
66 for (int i = 0; i < dim; i++) {
67 minPoint[i] = 0;
68 }
69
70 double[] init = new double[dim];
71
72
73 for (int i = 0; i < dim; i++) {
74 init[i] = minPoint[i];
75 }
76 doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-9);
77
78
79 for (int i = 0; i < dim; i++) {
80 init[i] = minPoint[i] + 3;
81 }
82 doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-5);
83
84
85 doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-9, 1e-7);
86 }
87
88 @Test
89 void testQuadratic() {
90 final MultivariateFunction func = new MultivariateFunction() {
91 public double value(double[] x) {
92 final double a = x[0] - 1;
93 final double b = x[1] - 1;
94 return a * a + b * b + 1;
95 }
96 };
97
98 int dim = 2;
99 final double[] minPoint = new double[dim];
100 for (int i = 0; i < dim; i++) {
101 minPoint[i] = 1;
102 }
103
104 double[] init = new double[dim];
105
106
107 for (int i = 0; i < dim; i++) {
108 init[i] = minPoint[i];
109 }
110 doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
111
112
113 for (int i = 0; i < dim; i++) {
114 init[i] = minPoint[i] - 20;
115 }
116 doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
117 }
118
119 @Test
120 void testMaximizeQuadratic() {
121 final MultivariateFunction func = new MultivariateFunction() {
122 public double value(double[] x) {
123 final double a = x[0] - 1;
124 final double b = x[1] - 1;
125 return -a * a - b * b + 1;
126 }
127 };
128
129 int dim = 2;
130 final double[] maxPoint = new double[dim];
131 for (int i = 0; i < dim; i++) {
132 maxPoint[i] = 1;
133 }
134
135 double[] init = new double[dim];
136
137
138 for (int i = 0; i < dim; i++) {
139 init[i] = maxPoint[i];
140 }
141 doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
142
143
144 for (int i = 0; i < dim; i++) {
145 init[i] = maxPoint[i] - 20;
146 }
147 doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
148 }
149
150
151
152
153
154
155
156
157 @Test
158 void testRelativeToleranceOnScaledValues() {
159 final MultivariateFunction func = new MultivariateFunction() {
160 public double value(double[] x) {
161 final double a = x[0] - 1;
162 final double b = x[1] - 1;
163 return a * a * FastMath.sqrt(FastMath.abs(a)) + b * b + 1;
164 }
165 };
166
167 int dim = 2;
168 final double[] minPoint = new double[dim];
169 for (int i = 0; i < dim; i++) {
170 minPoint[i] = 1;
171 }
172
173 double[] init = new double[dim];
174
175 for (int i = 0; i < dim; i++) {
176 init[i] = minPoint[i] - 20;
177 }
178
179 final double relTol = 1e-10;
180
181 final int maxEval = 1000;
182
183
184 final PowellOptimizer optim = new PowellOptimizer(relTol, 1e-100);
185
186 final PointValuePair funcResult = optim.optimize(new MaxEval(maxEval),
187 new ObjectiveFunction(func),
188 GoalType.MINIMIZE,
189 new InitialGuess(init));
190 final double funcValue = func.value(funcResult.getPoint());
191 final int funcEvaluations = optim.getEvaluations();
192
193 final double scale = 1e10;
194 final MultivariateFunction funcScaled = new MultivariateFunction() {
195 public double value(double[] x) {
196 return scale * func.value(x);
197 }
198 };
199
200 final PointValuePair funcScaledResult = optim.optimize(new MaxEval(maxEval),
201 new ObjectiveFunction(funcScaled),
202 GoalType.MINIMIZE,
203 new InitialGuess(init));
204 final double funcScaledValue = funcScaled.value(funcScaledResult.getPoint());
205 final int funcScaledEvaluations = optim.getEvaluations();
206
207
208
209 assertEquals(1, funcScaledValue / (scale * funcValue), relTol);
210
211
212 assertEquals(funcEvaluations, funcScaledEvaluations);
213 }
214
215
216
217
218
219
220
221
222
223
224 private void doTest(MultivariateFunction func,
225 double[] optimum,
226 double[] init,
227 GoalType goal,
228 double fTol,
229 double pointTol) {
230 final PowellOptimizer optim = new PowellOptimizer(fTol, FastMath.ulp(1d));
231
232 final PointValuePair result = optim.optimize(new MaxEval(1000),
233 new ObjectiveFunction(func),
234 goal,
235 new InitialGuess(init));
236 final double[] point = result.getPoint();
237
238 for (int i = 0, dim = optimum.length; i < dim; i++) {
239 assertEquals(optimum[i], point[i], pointTol, "found[" + i + "]=" + point[i] + " value=" + result.getValue());
240 }
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254 private void doTest(MultivariateFunction func,
255 double[] optimum,
256 double[] init,
257 GoalType goal,
258 double fTol,
259 double fLineTol,
260 double pointTol) {
261 final PowellOptimizer optim = new PowellOptimizer(fTol, FastMath.ulp(1d),
262 fLineTol, FastMath.ulp(1d));
263
264 final PointValuePair result = optim.optimize(new MaxEval(1000),
265 new ObjectiveFunction(func),
266 goal,
267 new InitialGuess(init));
268 final double[] point = result.getPoint();
269
270 for (int i = 0, dim = optimum.length; i < dim; i++) {
271 assertEquals(optimum[i], point[i], pointTol, "found[" + i + "]=" + point[i] + " value=" + result.getValue());
272 }
273
274 assertTrue(optim.getIterations() > 0);
275 }
276 }