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