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