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.geometry.euclidean.twod.Vector2D;
26  import org.hipparchus.optim.InitialGuess;
27  import org.hipparchus.optim.MaxEval;
28  import org.hipparchus.optim.PointValuePair;
29  import org.hipparchus.optim.SimpleValueChecker;
30  import org.hipparchus.optim.nonlinear.scalar.gradient.CircleScalar;
31  import org.hipparchus.optim.nonlinear.scalar.gradient.NonLinearConjugateGradientOptimizer;
32  import org.hipparchus.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
33  import org.hipparchus.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
34  import org.hipparchus.random.GaussianRandomGenerator;
35  import org.hipparchus.random.JDKRandomGenerator;
36  import org.hipparchus.random.RandomVectorGenerator;
37  import org.hipparchus.random.UncorrelatedRandomVectorGenerator;
38  import org.junit.Assert;
39  import org.junit.Test;
40  
41  public class MultiStartMultivariateOptimizerTest {
42      @Test
43      public void testCircleFitting() {
44          CircleScalar circle = new CircleScalar();
45          circle.addPoint( 30.0,  68.0);
46          circle.addPoint( 50.0,  -6.0);
47          circle.addPoint(110.0, -20.0);
48          circle.addPoint( 35.0,  15.0);
49          circle.addPoint( 45.0,  97.0);
50          // TODO: the wrapper around NonLinearConjugateGradientOptimizer is a temporary hack for
51          // version 3.1 of the library. It should be removed when NonLinearConjugateGradientOptimizer
52          // will officially be declared as implementing MultivariateDifferentiableOptimizer
53          GradientMultivariateOptimizer underlying
54              = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE,
55                                                        new SimpleValueChecker(1e-10, 1e-10));
56          JDKRandomGenerator g = new JDKRandomGenerator();
57          g.setSeed(753289573253l);
58          RandomVectorGenerator generator
59              = new UncorrelatedRandomVectorGenerator(new double[] { 50, 50 },
60                                                      new double[] { 10, 10 },
61                                                      new GaussianRandomGenerator(g));
62          int nbStarts = 10;
63          MultiStartMultivariateOptimizer optimizer
64              = new MultiStartMultivariateOptimizer(underlying, nbStarts, generator);
65          PointValuePair optimum
66              = optimizer.optimize(new MaxEval(1000),
67                                   circle.getObjectiveFunction(),
68                                   circle.getObjectiveFunctionGradient(),
69                                   GoalType.MINIMIZE,
70                                   new InitialGuess(new double[] { 98.680, 47.345 }));
71          Assert.assertEquals(1000, optimizer.getMaxEvaluations());
72          PointValuePair[] optima = optimizer.getOptima();
73          Assert.assertEquals(nbStarts, optima.length);
74          for (PointValuePair o : optima) {
75              // we check the results of all intermediate restarts here (there are 10 such results)
76              Vector2D center = new Vector2D(o.getPointRef()[0], o.getPointRef()[1]);
77              Assert.assertTrue(69.9592 < circle.getRadius(center));
78              Assert.assertTrue(69.9602 > circle.getRadius(center));
79              Assert.assertTrue(96.0745 < center.getX());
80              Assert.assertTrue(96.0762 > center.getX());
81              Assert.assertTrue(48.1344 < center.getY());
82              Assert.assertTrue(48.1354 > center.getY());
83          }
84  
85          Assert.assertTrue(optimizer.getEvaluations() > 850);
86          Assert.assertTrue(optimizer.getEvaluations() < 900);
87  
88          Assert.assertEquals(3.1267527, optimum.getValue(), 1e-8);
89      }
90  
91      @Test
92      public void testRosenbrock() {
93          Rosenbrock rosenbrock = new Rosenbrock();
94          SimplexOptimizer underlying
95              = new SimplexOptimizer(new SimpleValueChecker(-1, 1e-3));
96          NelderMeadSimplex simplex = new NelderMeadSimplex(new double[][] {
97                  { -1.2,  1.0 },
98                  { 0.9, 1.2 } ,
99                  {  3.5, -2.3 }
100             });
101         JDKRandomGenerator g = new JDKRandomGenerator();
102         g.setSeed(16069223052l);
103         RandomVectorGenerator generator
104             = new UncorrelatedRandomVectorGenerator(2, new GaussianRandomGenerator(g));
105         int nbStarts = 10;
106         MultiStartMultivariateOptimizer optimizer
107             = new MultiStartMultivariateOptimizer(underlying, nbStarts, generator);
108         PointValuePair optimum
109             = optimizer.optimize(new MaxEval(1100),
110                                  new ObjectiveFunction(rosenbrock),
111                                  GoalType.MINIMIZE,
112                                  simplex,
113                                  new InitialGuess(new double[] { -1.2, 1.0 }));
114         Assert.assertEquals(nbStarts, optimizer.getOptima().length);
115 
116         Assert.assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
117         Assert.assertTrue(optimizer.getEvaluations() > 900);
118         Assert.assertTrue(optimizer.getEvaluations() < 1200);
119         Assert.assertTrue(optimum.getValue() < 5e-5);
120     }
121 
122     private static class Rosenbrock implements MultivariateFunction {
123         private int count;
124 
125         public Rosenbrock() {
126             count = 0;
127         }
128 
129         public double value(double[] x) {
130             ++count;
131             double a = x[1] - x[0] * x[0];
132             double b = 1 - x[0];
133             return 100 * a * a + b * b;
134         }
135 
136         public int getCount() {
137             return count;
138         }
139     }
140 }