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.math.optimization.fitting;
19
20 import org.apache.commons.math.FunctionEvaluationException;
21 import org.apache.commons.math.MathRuntimeException;
22 import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
23 import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
24 import org.apache.commons.math.optimization.OptimizationException;
25
26 /** This class implements a curve fitting specialized for polynomials.
27 * <p>Polynomial fitting is a very simple case of curve fitting. The
28 * estimated coefficients are the polynomial coefficients. They are
29 * searched by a least square estimator.</p>
30 * @version $Revision: 786479 $ $Date: 2009-06-19 08:36:16 -0400 (Fri, 19 Jun 2009) $
31 * @since 2.0
32 */
33
34 public class PolynomialFitter {
35
36 /** Fitter for the coefficients. */
37 private final CurveFitter fitter;
38
39 /** Polynomial degree. */
40 private final int degree;
41
42 /** Simple constructor.
43 * <p>The polynomial fitter built this way are complete polynomials,
44 * ie. a n-degree polynomial has n+1 coefficients.</p>
45 * @param degree maximal degree of the polynomial
46 * @param optimizer optimizer to use for the fitting
47 */
48 public PolynomialFitter(int degree, final DifferentiableMultivariateVectorialOptimizer optimizer) {
49 this.fitter = new CurveFitter(optimizer);
50 this.degree = degree;
51 }
52
53 /** Add an observed weighted (x,y) point to the sample.
54 * @param weight weight of the observed point in the fit
55 * @param x abscissa of the point
56 * @param y observed value of the point at x, after fitting we should
57 * have P(x) as close as possible to this value
58 */
59 public void addObservedPoint(double weight, double x, double y) {
60 fitter.addObservedPoint(weight, x, y);
61 }
62
63 /** Get the polynomial fitting the weighted (x, y) points.
64 * @return polynomial function best fitting the observed points
65 * @exception OptimizationException if the algorithm failed to converge
66 */
67 public PolynomialFunction fit()
68 throws OptimizationException {
69 try {
70 return new PolynomialFunction(fitter.fit(new ParametricPolynomial(), new double[degree + 1]));
71 } catch (FunctionEvaluationException fee) {
72 // this should never happen
73 throw MathRuntimeException.createInternalError(fee);
74 }
75 }
76
77 /** Dedicated parametric polynomial class. */
78 private static class ParametricPolynomial implements ParametricRealFunction {
79
80 /** {@inheritDoc} */
81 public double[] gradient(double x, double[] parameters)
82 throws FunctionEvaluationException {
83 final double[] gradient = new double[parameters.length];
84 double xn = 1.0;
85 for (int i = 0; i < parameters.length; ++i) {
86 gradient[i] = xn;
87 xn *= x;
88 }
89 return gradient;
90 }
91
92 /** {@inheritDoc} */
93 public double value(final double x, final double[] parameters) {
94 double y = 0;
95 for (int i = parameters.length - 1; i >= 0; --i) {
96 y = y * x + parameters[i];
97 }
98 return y;
99 }
100
101 }
102
103 }