View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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             // the function should never be called with out of range points
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 }