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