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  
18  package org.apache.commons.math4.legacy.optim.nonlinear.scalar.gradient;
19  
20  import java.util.ArrayList;
21  
22  import org.apache.commons.geometry.euclidean.twod.Vector2D;
23  import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
24  import org.apache.commons.math4.legacy.analysis.MultivariateVectorFunction;
25  import org.apache.commons.math4.legacy.optim.nonlinear.scalar.ObjectiveFunction;
26  import org.apache.commons.math4.legacy.optim.nonlinear.scalar.ObjectiveFunctionGradient;
27  
28  /**
29   * Class used in the tests.
30   */
31  public class CircleScalar {
32      private ArrayList<Vector2D> points;
33  
34      public CircleScalar() {
35          points  = new ArrayList<>();
36      }
37  
38      public void addPoint(double px, double py) {
39          points.add(Vector2D.of(px, py));
40      }
41  
42      public double getRadius(Vector2D center) {
43          double r = 0;
44          for (Vector2D point : points) {
45              r += point.distance(center);
46          }
47          return r / points.size();
48      }
49  
50      public ObjectiveFunction getObjectiveFunction() {
51          return new ObjectiveFunction(new MultivariateFunction() {
52                  @Override
53                  public double value(double[] params)  {
54                      Vector2D center = Vector2D.of(params[0], params[1]);
55                      double radius = getRadius(center);
56                      double sum = 0;
57                      for (Vector2D point : points) {
58                          double di = point.distance(center) - radius;
59                          sum += di * di;
60                      }
61                      return sum;
62                  }
63              });
64      }
65  
66      public ObjectiveFunctionGradient getObjectiveFunctionGradient() {
67          return new ObjectiveFunctionGradient(new MultivariateVectorFunction() {
68                  @Override
69                  public double[] value(double[] params) {
70                      Vector2D center = Vector2D.of(params[0], params[1]);
71                      double radius = getRadius(center);
72                      // gradient of the sum of squared residuals
73                      double dJdX = 0;
74                      double dJdY = 0;
75                      for (Vector2D pk : points) {
76                          double dk = pk.distance(center);
77                          dJdX += (center.getX() - pk.getX()) * (dk - radius) / dk;
78                          dJdY += (center.getY() - pk.getY()) * (dk - radius) / dk;
79                      }
80                      dJdX *= 2;
81                      dJdY *= 2;
82  
83                      return new double[] { dJdX, dJdY };
84                  }
85              });
86      }
87  }