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