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