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