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;
23
24 import org.hipparchus.analysis.MultivariateFunction;
25 import org.hipparchus.optim.InitialGuess;
26 import org.hipparchus.optim.MaxEval;
27 import org.hipparchus.optim.PointValuePair;
28 import org.hipparchus.optim.nonlinear.scalar.noderiv.AbstractSimplex;
29 import org.hipparchus.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
30 import org.hipparchus.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
31 import org.junit.jupiter.api.Test;
32
33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 import static org.junit.jupiter.api.Assertions.assertTrue;
35
36 class MultivariateFunctionMappingAdapterTest {
37 @Test
38 void testStartSimplexInsideRange() {
39 final BiQuadratic biQuadratic = new BiQuadratic(2.0, 2.5, 1.0, 3.0, 2.0, 3.0);
40 final MultivariateFunctionMappingAdapter wrapped
41 = new MultivariateFunctionMappingAdapter(biQuadratic,
42 biQuadratic.getLower(),
43 biQuadratic.getUpper());
44
45 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
46 final AbstractSimplex simplex = new NelderMeadSimplex(new double[][] {
47 wrapped.boundedToUnbounded(new double[] { 1.5, 2.75 }),
48 wrapped.boundedToUnbounded(new double[] { 1.5, 2.95 }),
49 wrapped.boundedToUnbounded(new double[] { 1.7, 2.90 })
50 });
51
52 final PointValuePair optimum
53 = optimizer.optimize(new MaxEval(300),
54 new ObjectiveFunction(wrapped),
55 simplex,
56 GoalType.MINIMIZE,
57 new InitialGuess(wrapped.boundedToUnbounded(new double[] { 1.5, 2.25 })));
58 final double[] bounded = wrapped.unboundedToBounded(optimum.getPoint());
59
60 assertEquals(biQuadratic.getBoundedXOptimum(), bounded[0], 2e-7);
61 assertEquals(biQuadratic.getBoundedYOptimum(), bounded[1], 2e-7);
62 }
63
64 @Test
65 void testOptimumOutsideRange() {
66 final BiQuadratic biQuadratic = new BiQuadratic(4.0, 0.0, 1.0, 3.0, 2.0, 3.0);
67 final MultivariateFunctionMappingAdapter wrapped
68 = new MultivariateFunctionMappingAdapter(biQuadratic,
69 biQuadratic.getLower(),
70 biQuadratic.getUpper());
71
72 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
73 final AbstractSimplex simplex = new NelderMeadSimplex(new double[][] {
74 wrapped.boundedToUnbounded(new double[] { 1.5, 2.75 }),
75 wrapped.boundedToUnbounded(new double[] { 1.5, 2.95 }),
76 wrapped.boundedToUnbounded(new double[] { 1.7, 2.90 })
77 });
78
79 final PointValuePair optimum
80 = optimizer.optimize(new MaxEval(100),
81 new ObjectiveFunction(wrapped),
82 simplex,
83 GoalType.MINIMIZE,
84 new InitialGuess(wrapped.boundedToUnbounded(new double[] { 1.5, 2.25 })));
85 final double[] bounded = wrapped.unboundedToBounded(optimum.getPoint());
86
87 assertEquals(biQuadratic.getBoundedXOptimum(), bounded[0], 2e-7);
88 assertEquals(biQuadratic.getBoundedYOptimum(), bounded[1], 2e-7);
89 }
90
91 @Test
92 void testUnbounded() {
93 final BiQuadratic biQuadratic = new BiQuadratic(4.0, 0.0,
94 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
95 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
96 final MultivariateFunctionMappingAdapter wrapped
97 = new MultivariateFunctionMappingAdapter(biQuadratic,
98 biQuadratic.getLower(),
99 biQuadratic.getUpper());
100
101 SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
102 final AbstractSimplex simplex = new NelderMeadSimplex(new double[][] {
103 wrapped.boundedToUnbounded(new double[] { 1.5, 2.75 }),
104 wrapped.boundedToUnbounded(new double[] { 1.5, 2.95 }),
105 wrapped.boundedToUnbounded(new double[] { 1.7, 2.90 })
106 });
107
108 final PointValuePair optimum
109 = optimizer.optimize(new MaxEval(300),
110 new ObjectiveFunction(wrapped),
111 simplex,
112 GoalType.MINIMIZE,
113 new InitialGuess(wrapped.boundedToUnbounded(new double[] { 1.5, 2.25 })));
114 final double[] bounded = wrapped.unboundedToBounded(optimum.getPoint());
115
116 assertEquals(biQuadratic.getBoundedXOptimum(), bounded[0], 2e-7);
117 assertEquals(biQuadratic.getBoundedYOptimum(), bounded[1], 2e-7);
118 }
119
120 @Test
121 void testHalfBounded() {
122 final BiQuadratic biQuadratic = new BiQuadratic(4.0, 4.0,
123 1.0, Double.POSITIVE_INFINITY,
124 Double.NEGATIVE_INFINITY, 3.0);
125 final MultivariateFunctionMappingAdapter wrapped
126 = new MultivariateFunctionMappingAdapter(biQuadratic,
127 biQuadratic.getLower(),
128 biQuadratic.getUpper());
129
130 SimplexOptimizer optimizer = new SimplexOptimizer(1e-13, 1e-30);
131 final AbstractSimplex simplex = new NelderMeadSimplex(new double[][] {
132 wrapped.boundedToUnbounded(new double[] { 1.5, 2.75 }),
133 wrapped.boundedToUnbounded(new double[] { 1.5, 2.95 }),
134 wrapped.boundedToUnbounded(new double[] { 1.7, 2.90 })
135 });
136
137 final PointValuePair optimum
138 = optimizer.optimize(new MaxEval(200),
139 new ObjectiveFunction(wrapped),
140 simplex,
141 GoalType.MINIMIZE,
142 new InitialGuess(wrapped.boundedToUnbounded(new double[] { 1.5, 2.25 })));
143 final double[] bounded = wrapped.unboundedToBounded(optimum.getPoint());
144
145 assertEquals(biQuadratic.getBoundedXOptimum(), bounded[0], 1e-7);
146 assertEquals(biQuadratic.getBoundedYOptimum(), bounded[1], 1e-7);
147 }
148
149 private static class BiQuadratic implements MultivariateFunction {
150
151 private final double xOptimum;
152 private final double yOptimum;
153
154 private final double xMin;
155 private final double xMax;
156 private final double yMin;
157 private final double yMax;
158
159 public BiQuadratic(final double xOptimum, final double yOptimum,
160 final double xMin, final double xMax,
161 final double yMin, final double yMax) {
162 this.xOptimum = xOptimum;
163 this.yOptimum = yOptimum;
164 this.xMin = xMin;
165 this.xMax = xMax;
166 this.yMin = yMin;
167 this.yMax = yMax;
168 }
169
170 public double value(double[] point) {
171
172 assertTrue(point[0] >= xMin);
173 assertTrue(point[0] <= xMax);
174 assertTrue(point[1] >= yMin);
175 assertTrue(point[1] <= yMax);
176
177 final double dx = point[0] - xOptimum;
178 final double dy = point[1] - yOptimum;
179 return dx * dx + dy * dy;
180
181 }
182
183 public double[] getLower() {
184 return new double[] { xMin, yMin };
185 }
186
187 public double[] getUpper() {
188 return new double[] { xMax, yMax };
189 }
190
191 public double getBoundedXOptimum() {
192 return (xOptimum < xMin) ? xMin : ((xOptimum > xMax) ? xMax : xOptimum);
193 }
194
195 public double getBoundedYOptimum() {
196 return (yOptimum < yMin) ? yMin : ((yOptimum > yMax) ? yMax : yOptimum);
197 }
198 }
199 }