/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.math.impl.interpolation; import static org.testng.Assert.assertEquals; import java.util.function.Function; import org.testng.annotations.Test; import com.opengamma.strata.collect.array.DoubleMatrix; import com.opengamma.strata.math.impl.function.DoubleFunction1D; import com.opengamma.strata.math.impl.function.RealPolynomialFunction1D; import com.opengamma.strata.math.impl.regression.LeastSquaresRegressionResult; import com.opengamma.strata.math.impl.statistics.descriptive.MeanCalculator; import com.opengamma.strata.math.impl.statistics.descriptive.SampleStandardDeviationCalculator; /** * Test. */ @Test public class PolynomialsLeastSquaresFitterTest { private static final double EPS = 1e-14; private final Function<double[], Double> _meanCal = new MeanCalculator(); private final Function<double[], Double> _stdCal = new SampleStandardDeviationCalculator(); /** * Checks coefficients of polynomial f(x) are recovered and residuals, { y_i -f(x_i) }, are accurate */ public void PolynomialFunctionRecoverTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final double[] coeff = new double[] {3.4, 5.6, 1., -4. }; DoubleFunction1D func = new RealPolynomialFunction1D(coeff); final int degree = coeff.length - 1; final int nPts = 7; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; for (int i = 0; i < nPts; ++i) { xValues[i] = -5. + 10 * i / (nPts - 1); yValues[i] = func.applyAsDouble(xValues[i]); } double[] yValuesNorm = new double[nPts]; final double mean = _meanCal.apply(xValues); final double std = _stdCal.apply(xValues); final double ratio = mean / std; for (int i = 0; i < nPts; ++i) { final double tmp = xValues[i] / std - ratio; yValuesNorm[i] = func.applyAsDouble(tmp); } /** * Tests for regress(..) */ LeastSquaresRegressionResult result = regObj.regress(xValues, yValues, degree); double[] coeffResult = result.getBetas(); for (int i = 0; i < degree + 1; ++i) { assertEquals(coeff[i], coeffResult[i], EPS * Math.abs(coeff[i])); } final double[] residuals = result.getResiduals(); func = new RealPolynomialFunction1D(coeffResult); double[] yValuesFit = new double[nPts]; for (int i = 0; i < nPts; ++i) { yValuesFit[i] = func.applyAsDouble(xValues[i]); } for (int i = 0; i < nPts; ++i) { assertEquals(Math.abs(yValuesFit[i] - yValues[i]), 0., Math.abs(yValues[i]) * EPS); } for (int i = 0; i < nPts; ++i) { assertEquals(Math.abs(yValuesFit[i] - yValues[i]), Math.abs(residuals[i]), Math.abs(yValues[i]) * EPS); } double sum = 0.; for (int i = 0; i < nPts; ++i) { sum += residuals[i] * residuals[i]; } sum = Math.sqrt(sum); /** * Tests for regressVerbose(.., false) */ PolynomialsLeastSquaresFitterResult resultVer = regObj.regressVerbose(xValues, yValues, degree, false); coeffResult = resultVer.getCoeff(); func = new RealPolynomialFunction1D(coeffResult); for (int i = 0; i < nPts; ++i) { yValuesFit[i] = func.applyAsDouble(xValues[i]); } assertEquals(nPts - (degree + 1), resultVer.getDof(), 0); for (int i = 0; i < degree + 1; ++i) { assertEquals(coeff[i], coeffResult[i], EPS * Math.abs(coeff[i])); } for (int i = 0; i < nPts; ++i) { assertEquals(Math.abs(yValuesFit[i] - yValues[i]), 0., Math.abs(yValues[i]) * EPS); } assertEquals(sum, resultVer.getDiffNorm(), EPS); /** * Tests for regressVerbose(.., true) */ PolynomialsLeastSquaresFitterResult resultNorm = regObj.regressVerbose(xValues, yValuesNorm, degree, true); coeffResult = resultNorm.getCoeff(); final double[] meanAndStd = resultNorm.getMeanAndStd(); assertEquals(nPts - (degree + 1), resultNorm.getDof(), 0); assertEquals(mean, meanAndStd[0], EPS); assertEquals(std, meanAndStd[1], EPS); for (int i = 0; i < degree + 1; ++i) { assertEquals(coeff[i], coeffResult[i], EPS * Math.abs(coeff[i])); } func = new RealPolynomialFunction1D(coeffResult); for (int i = 0; i < nPts; ++i) { final double tmp = xValues[i] / std - ratio; yValuesFit[i] = func.applyAsDouble(tmp); } for (int i = 0; i < nPts; ++i) { assertEquals(Math.abs(yValuesFit[i] - yValuesNorm[i]), 0., Math.abs(yValuesNorm[i]) * EPS); } sum = 0.; for (int i = 0; i < nPts; ++i) { sum += (yValuesFit[i] - yValuesNorm[i]) * (yValuesFit[i] - yValuesNorm[i]); } sum = Math.sqrt(sum); assertEquals(sum, resultNorm.getDiffNorm(), EPS); } /** * */ public void RmatrixTest() { final PolynomialsLeastSquaresFitter regObj1 = new PolynomialsLeastSquaresFitter(); final double[] xValues = new double[] {-1., 0, 1. }; final double[] yValues = new double[] {1., 0, 1. }; final double[][] rMatrix = new double[][] { {-Math.sqrt(3.), 0., -2. / Math.sqrt(3.)}, {0., -Math.sqrt(2.), 0.}, {0., 0., -Math.sqrt(2. / 3.)} }; final int degree = 2; PolynomialsLeastSquaresFitterResult resultVer = regObj1.regressVerbose(xValues, yValues, degree, false); DoubleMatrix rMatResult = resultVer.getRMat(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { assertEquals(rMatrix[i][j], rMatResult.get(i, j), EPS); } } final PolynomialsLeastSquaresFitter regObj2 = new PolynomialsLeastSquaresFitter(); PolynomialsLeastSquaresFitterResult resultNorm = regObj2.regressVerbose(xValues, yValues, degree, true); rMatResult = resultNorm.getRMat(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { assertEquals(rMatrix[i][j], rMatResult.get(i, j), EPS); } } } /** * An error is thrown if rescaling of xValues is NOT used and we try to access data, mean and standard deviation */ @Test(expectedExceptions = IllegalArgumentException.class) public void NormalisationErrorTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; PolynomialsLeastSquaresFitterResult result = regObj.regressVerbose(xValues, yValues, degree, false); result.getMeanAndStd(); } /** * Number of data points should be larger than (degree + 1) of a polynomial */ @Test(expectedExceptions = IllegalArgumentException.class) public void DataShortTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 6; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void DataShortVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 6; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void DataShortVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 6; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regressVerbose(xValues, yValues, degree, true); } /** * Degree of polynomial must be positive */ @Test(expectedExceptions = IllegalArgumentException.class) public void MinusDegreeTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = -4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void MinusDegreeVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = -4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void MinusDegreeVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = -4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1 }; regObj.regressVerbose(xValues, yValues, degree, true); } /** * xValues length should be the same as yValues length */ @Test(expectedExceptions = IllegalArgumentException.class) public void WrongDataLengthTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1, 2 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void WrongDataLengthVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1, 2 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void WrongDataLengthVerboseTureTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 5, 6 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 1, 2 }; regObj.regressVerbose(xValues, yValues, degree, true); } /** * An error is thrown if too many repeated data are found */ @Test(expectedExceptions = IllegalArgumentException.class) public void RepeatDataTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 1, 1 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 2 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void RepeatDataVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 1, 1 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 2 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void RepeatDataVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1, 2, 3, 1, 1 }; final double[] yValues = new double[] {1, 2, 3, 4, 2, 2 }; regObj.regressVerbose(xValues, yValues, degree, true); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void ExtremeValueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1e-307, 2e-307, 3e18, 4 }; final double[] yValues = new double[] {1, 2, 3, 4, 5 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void ExtremeValueVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1e-307, 2e-307, 3e18, 4 }; final double[] yValues = new double[] {1, 2, 3, 4, 5 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void ExtremeValueVerboseTrueAlphaTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final double[] xValues = new double[] {0, 1e-307, 2e-307, 3e-307, 4 }; final double[] yValues = new double[] {1, 2, 3, 4, 5 }; regObj.regressVerbose(xValues, yValues, degree, true); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NullTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; xValues = null; yValues = null; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NullVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; xValues = null; yValues = null; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NullVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; xValues = null; yValues = null; regObj.regressVerbose(xValues, yValues, degree, true); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void InfinityTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; final double zero = 0.; for (int i = 0; i < nPts; ++i) { xValues[i] = 1. / zero; yValues[i] = 1. / zero; } regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void InfinityVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; final double zero = 0.; for (int i = 0; i < nPts; ++i) { xValues[i] = 1. / zero; yValues[i] = 1. / zero; } regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void InfinityVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; final double zero = 0.; for (int i = 0; i < nPts; ++i) { xValues[i] = 1. / zero; yValues[i] = 1. / zero; } regObj.regressVerbose(xValues, yValues, degree, true); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NaNTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; for (int i = 0; i < nPts; ++i) { xValues[i] = Double.NaN; yValues[i] = Double.NaN; } regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NaNVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; for (int i = 0; i < nPts; ++i) { xValues[i] = Double.NaN; yValues[i] = Double.NaN; } regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void NaNVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; final int nPts = 5; double[] xValues = new double[nPts]; double[] yValues = new double[nPts]; for (int i = 0; i < nPts; ++i) { xValues[i] = Double.NaN; yValues[i] = Double.NaN; } regObj.regressVerbose(xValues, yValues, degree, true); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void LargeNumberTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; double[] xValues = new double[] {1, 2, 3, 4e2, 5, 6, 7 }; double[] yValues = new double[] {1, 2, 3, 4, 5, 6, 7 }; regObj.regress(xValues, yValues, degree); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void LargeNumberVerboseFalseTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 4; double[] xValues = new double[] {1, 2, 3, 4e2, 5, 6, 7 }; double[] yValues = new double[] {1, 2, 3, 4, 5, 6, 7 }; regObj.regressVerbose(xValues, yValues, degree, false); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void LargeNumberVerboseTrueTest() { final PolynomialsLeastSquaresFitter regObj = new PolynomialsLeastSquaresFitter(); final int degree = 6; double[] xValues = new double[] {1, 2, 3, 4e17, 5, 6, 7 }; double[] yValues = new double[] {1, 2, 3, 4, 5, 6, 7 }; regObj.regressVerbose(xValues, yValues, degree, true); } }