package umontreal.iro.lecuyer.functionfit;
import java.io.Serializable;
import umontreal.iro.lecuyer.functions.Polynomial;
import cern.colt.matrix.DoubleMatrix2D;
import cern.colt.matrix.impl.DenseDoubleMatrix2D;
import cern.colt.matrix.linalg.Algebra;
/**
* Represents a polynomial obtained by the least squares method on a set of points.
* More specifically, let
* (x0, y0),…,(xn, yn) be a set of points and
* p(x) the constructed polynomial of degree m. The constructed polynomial
* minimizes the square error
*
*
* E2 = ∑i=0n[yi - p(xi)]2.
*
*
*/
public class LeastSquares extends Polynomial implements Serializable {
private static final long serialVersionUID = -4997132164503234983L;
private static final Algebra alg = new Algebra ();
private double[] x;
private double[] y;
/**
* Constructs a new least squares polynomial with points (x[0],
* y[0]),..., (x[n], y[n]). The constructed polynomial has degree
* degree.
*
* @param x the x coordinates of the points.
*
* @param y the y coordinates of the points.
*
* @param degree the degree of the polynomial.
*
* @exception NullPointerException if x or y are null.
*
* @exception IllegalArgumentException if the lengths of x and y are different,
* or if less than degree + 1 points are specified.
*
*/
public LeastSquares (double[] x, double[] y, int degree) {
super (getCoefficients (x, y, degree));
this.x = x.clone ();
this.y = y.clone ();
}
/**
* Computes and returns the coefficients of the fitting polynomial of
* degree degree.
* The coordinates of the given points are (x[i], y[i]).
*
* @param x the x coordinates of the points.
*
* @param y the y coordinates of the points.
*
* @param degree the degree of the polynomial.
*
* @return the coefficients of the fitting polynomial.
*
*/
public static double[] getCoefficients (double[] x, double[] y,
int degree) {
if (x.length != y.length)
throw new IllegalArgumentException ("Length of x and y not equal");
if (x.length < degree + 1)
throw new IllegalArgumentException ("Not enough points");
final double[] xSums = new double[2 * degree + 1];
final double[] xySums = new double[degree + 1];
xSums[0] = x.length;
for (int i = 0; i < x.length; i++) {
double xv = x[i];
xySums[0] += y[i];
for (int j = 1; j <= 2 * degree; j++) {
xSums[j] += xv;
if (j <= degree)
xySums[j] += xv * y[i];
xv *= x[i];
}
}
final DoubleMatrix2D A = new DenseDoubleMatrix2D (degree + 1, degree + 1);
final DoubleMatrix2D B = new DenseDoubleMatrix2D (degree + 1, 1);
for (int i = 0; i <= degree; i++) {
for (int j = 0; j <= degree; j++) {
final int d = i + j;
A.setQuick (i, j, xSums[d]);
}
B.setQuick (i, 0, xySums[i]);
}
final DoubleMatrix2D aVec = alg.solve (A, B);
return aVec.viewColumn (0).toArray ();
}
/**
* Returns the x coordinates of the fitted points.
*
* @return the x coordinates of the fitted points.
*
*/
public double[] getX() {
return x;
}
/**
* Returns the y coordinates of the fitted points.
*
* @return the y coordinates of the fitted points.
*
*/
public double[] getY() {
return y;
}
/**
* Calls {@link umontreal.iro.lecuyer.functionfit.PolInterp#toString(double[], double[]) toString}
* with the associated points.
*
* @return a string containing the points.
*
*/
public String toString() {
return PolInterp.toString (x, y);
}
@Override
public LeastSquares clone() {
final LeastSquares ls = (LeastSquares) super.clone ();
ls.x = x.clone ();
ls.y = y.clone ();
return ls;
}
}
Ads help maintain this website.