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.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             // the function should never be called with out of range points
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 }