PolynomialCurveFitter.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.fitting;

  22. import java.util.Collection;

  23. import org.hipparchus.analysis.polynomials.PolynomialFunction;
  24. import org.hipparchus.exception.MathRuntimeException;
  25. import org.hipparchus.linear.DiagonalMatrix;
  26. import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder;
  27. import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;

  28. /**
  29.  * Fits points to a {@link
  30.  * org.hipparchus.analysis.polynomials.PolynomialFunction.Parametric polynomial}
  31.  * function.
  32.  * <br>
  33.  * The size of the {@link #withStartPoint(double[]) initial guess} array defines the
  34.  * degree of the polynomial to be fitted.
  35.  * They must be sorted in increasing order of the polynomial's degree.
  36.  * The optimal values of the coefficients will be returned in the same order.
  37.  *
  38.  */
  39. public class PolynomialCurveFitter extends AbstractCurveFitter {
  40.     /** Parametric function to be fitted. */
  41.     private static final PolynomialFunction.Parametric FUNCTION = new PolynomialFunction.Parametric();
  42.     /** Initial guess. */
  43.     private final double[] initialGuess;
  44.     /** Maximum number of iterations of the optimization algorithm. */
  45.     private final int maxIter;

  46.     /**
  47.      * Constructor used by the factory methods.
  48.      *
  49.      * @param initialGuess Initial guess.
  50.      * @param maxIter Maximum number of iterations of the optimization algorithm.
  51.      * @throws MathRuntimeException if {@code initialGuess} is {@code null}.
  52.      */
  53.     private PolynomialCurveFitter(double[] initialGuess, int maxIter) {
  54.         this.initialGuess = initialGuess.clone();
  55.         this.maxIter = maxIter;
  56.     }

  57.     /**
  58.      * Creates a default curve fitter.
  59.      * Zero will be used as initial guess for the coefficients, and the maximum
  60.      * number of iterations of the optimization algorithm is set to
  61.      * {@link Integer#MAX_VALUE}.
  62.      *
  63.      * @param degree Degree of the polynomial to be fitted.
  64.      * @return a curve fitter.
  65.      *
  66.      * @see #withStartPoint(double[])
  67.      * @see #withMaxIterations(int)
  68.      */
  69.     public static PolynomialCurveFitter create(int degree) {
  70.         return new PolynomialCurveFitter(new double[degree + 1], Integer.MAX_VALUE);
  71.     }

  72.     /**
  73.      * Configure the start point (initial guess).
  74.      * @param newStart new start point (initial guess)
  75.      * @return a new instance.
  76.      */
  77.     public PolynomialCurveFitter withStartPoint(double[] newStart) {
  78.         return new PolynomialCurveFitter(newStart.clone(),
  79.                                          maxIter);
  80.     }

  81.     /**
  82.      * Configure the maximum number of iterations.
  83.      * @param newMaxIter maximum number of iterations
  84.      * @return a new instance.
  85.      */
  86.     public PolynomialCurveFitter withMaxIterations(int newMaxIter) {
  87.         return new PolynomialCurveFitter(initialGuess,
  88.                                          newMaxIter);
  89.     }

  90.     /** {@inheritDoc} */
  91.     @Override
  92.     protected LeastSquaresProblem getProblem(Collection<WeightedObservedPoint> observations) {
  93.         // Prepare least-squares problem.
  94.         final int len = observations.size();
  95.         final double[] target  = new double[len];
  96.         final double[] weights = new double[len];

  97.         int i = 0;
  98.         for (WeightedObservedPoint obs : observations) {
  99.             target[i]  = obs.getY();
  100.             weights[i] = obs.getWeight();
  101.             ++i;
  102.         }

  103.         final AbstractCurveFitter.TheoreticalValuesFunction model =
  104.                 new AbstractCurveFitter.TheoreticalValuesFunction(FUNCTION, observations);

  105.         if (initialGuess == null) {
  106.             throw MathRuntimeException.createInternalError();
  107.         }

  108.         // Return a new least squares problem set up to fit a polynomial curve to the
  109.         // observed points.
  110.         return new LeastSquaresBuilder().
  111.                 maxEvaluations(Integer.MAX_VALUE).
  112.                 maxIterations(maxIter).
  113.                 start(initialGuess).
  114.                 target(target).
  115.                 weight(new DiagonalMatrix(weights)).
  116.                 model(model.getModelFunction(), model.getModelFunctionJacobian()).
  117.                 build();

  118.     }

  119. }