/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.interpolation;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.opengamma.analytics.math.function.PiecewisePolynomialFunction1D;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle;
import com.opengamma.analytics.math.minimization.DoubleRangeLimitTransform;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class Interpolator1DTest {
private static final double EPS = 1e-6;
/**
*
*/
@Test
public void firstDerivativeInterpolatorsTest() {
final double[][] xValues = new double[][] { {1., 2., 3., 4., 5., 6. }, {2., 2.1, 4., 5.1, 5.22, 6.8 } };
final double[][] yValues = new double[][] { {1., 1.1, 2., 3., 5.9, 6. }, {1., 2.1, 3., 3.1, 3.22, 4.8 } };
final int dim = xValues.length;
final int nData = xValues[0].length;
final int nKeys = 11 * nData;
final Interpolator1D[] interp = new Interpolator1D[] {new DoubleQuadraticInterpolator1D(), new ExponentialInterpolator1D(), new LinearInterpolator1D(),
new LogLinearInterpolator1D(), new NaturalCubicSplineInterpolator1D(), new PCHIPInterpolator1D(), new PCHIPYieldCurveInterpolator1D(),
new LogNaturalCubicMonotonicityPreservingInterpolator1D(), new StepInterpolator1D(), new StepUpperInterpolator1D(), new TimeSquareInterpolator1D() };
final int nMethods = interp.length;
for (int j = 0; j < dim; ++j) {
for (int i = 0; i < nMethods; ++i) {
// System.out.println(i);
Interpolator1DDataBundle data = interp[i].getDataBundleFromSortedArrays(xValues[j], yValues[j]);
final double xMin = xValues[j][0];
final double xMax = xValues[j][nData - 1];
for (int m = 0; m < nKeys - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys;
// System.out.println(xKey);
assertEquals(interp[i].firstDerivative(data, xKey), 0.5 * (interp[i].interpolate(data, xKey + EPS) - interp[i].interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
}
final double[][] xValues1 = new double[][] { {1., 2., 3., 4. }, {1., 2.1, 2.9, 4.1 } };
final double[][] yValues1 = new double[][] { {1., 5, 8., 15. }, {1., 5, 8., 15. } };
final int dim1 = 2;
final int nData1 = xValues1[0].length;
final int nKeys1 = 11 * nData1;
final Interpolator1D interp1 = new QuadraticSplineInterpolator1D();
for (int i = 0; i < dim1; ++i) {
final double xMin = xValues1[i][0];
final double xMax = xValues1[i][nData1 - 1];
for (int m = 0; m < nKeys1 - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys1;
Interpolator1DDataBundle data = interp1.getDataBundleFromSortedArrays(xValues1[i], yValues1[i]);
assertEquals(interp1.firstDerivative(data, xKey), 0.5 * (interp1.interpolate(data, xKey + EPS) - interp1.interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
final double[][] xValues2 = new double[][] { {1., 2., 3., 4. }, {1., 2.1, 2.9, 4.1 } };
final double[][] yValues2 = new double[][] { {1., 5, 8., 15. }, {1., 5, 8., 15. } };
final int dim2 = 2;
final int nData2 = xValues2[0].length;
final int nKeys2 = 11 * nData2;
final Interpolator1D interp2 = new MonotonicIncreasingInterpolator1D();
for (int i = 0; i < dim2; ++i) {
final double xMin = xValues2[i][0];
final double xMax = xValues2[i][nData2 - 1];
for (int m = 0; m < nKeys2 - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys2;
Interpolator1DDataBundle data = interp2.getDataBundleFromSortedArrays(xValues2[i], yValues2[i]);
assertEquals(interp2.firstDerivative(data, xKey), 0.5 * (interp2.interpolate(data, xKey + EPS) - interp2.interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
}
/**
* Data length = 3
*/
@Test
public void firstDerivativeInterpolatorsThreePointsTest() {
final double[][] xValues = new double[][] { {1., 2., 3. }, {2., 2.1, 4. } };
final double[][] yValues = new double[][] { {1., 1.1, 2. }, {1., 2.1, 3. } };
final int dim = xValues.length;
final int nData = xValues[0].length;
final int nKeys = 11 * nData;
final Interpolator1D[] interp = new Interpolator1D[] {new DoubleQuadraticInterpolator1D(), new ExponentialInterpolator1D(), new LinearInterpolator1D(),
new LogLinearInterpolator1D(), new NaturalCubicSplineInterpolator1D(), new PCHIPInterpolator1D(), new PCHIPYieldCurveInterpolator1D(),
new StepInterpolator1D(), new StepUpperInterpolator1D(), new TimeSquareInterpolator1D() };
final int nMethods = interp.length;
for (int j = 0; j < dim; ++j) {
for (int i = 0; i < nMethods; ++i) {
// System.out.println(i);
Interpolator1DDataBundle data = interp[i].getDataBundleFromSortedArrays(xValues[j], yValues[j]);
final double xMin = xValues[j][0];
final double xMax = xValues[j][nData - 1];
for (int m = 0; m < nKeys - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys;
// System.out.println(xKey);
assertEquals(interp[i].firstDerivative(data, xKey), 0.5 * (interp[i].interpolate(data, xKey + EPS) - interp[i].interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
}
}
/**
* Data length = 2
*/
@Test
public void firstDerivativeInterpolatorsTwoPointsTest2() {
final double[][] xValues = new double[][] { {1., 2. }, {2., 2.1 } };
final double[][] yValues = new double[][] { {1., 1.1 }, {1., 2.1 } };
final int dim = xValues.length;
final int nData = xValues[0].length;
final int nKeys = 11 * nData;
final Interpolator1D[] interp = new Interpolator1D[] {new DoubleQuadraticInterpolator1D(), new ExponentialInterpolator1D(), new LinearInterpolator1D(),
new LogLinearInterpolator1D(), new NaturalCubicSplineInterpolator1D(), new PCHIPYieldCurveInterpolator1D(),
new StepInterpolator1D(), new StepUpperInterpolator1D(), new TimeSquareInterpolator1D() };
final int nMethods = interp.length;
for (int j = 0; j < dim; ++j) {
for (int i = 0; i < nMethods; ++i) {
// System.out.println(i);
Interpolator1DDataBundle data = interp[i].getDataBundleFromSortedArrays(xValues[j], yValues[j]);
final double xMin = xValues[j][0];
final double xMax = xValues[j][nData - 1];
for (int m = 0; m < nKeys - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys;
// System.out.println(xKey);
assertEquals(interp[i].firstDerivative(data, xKey), 0.5 * (interp[i].interpolate(data, xKey + EPS) - interp[i].interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
}
}
/**
* Test for interpolators calling another interpolator
*/
@Test
public void firstDerivativeInterpolatorsSecondaryTest() {
final double[][] xValues = new double[][] { {1., 2., 3., 4., 5., 6. }, {1.1, 1.3, 3.8, 4.1, 5.9, 6. } };
final double[][] yValues = new double[][] { {1., 1.1, 2., 3., 5.9, 6. }, {1., 1.12, 1., 3.4, 5.9, 3.2 } };
final int dim = xValues.length;
final int nData = xValues[0].length;
final int nKeys = 11 * nData;
final Interpolator1D interpPre = new DoubleQuadraticInterpolator1D();
final Interpolator1D[] interp = new Interpolator1D[] {new CombinedInterpolatorExtrapolator(interpPre), new TransformedInterpolator1D(interpPre, new DoubleRangeLimitTransform(0, 1)) };
final int nMethods = interp.length;
for (int j = 0; j < dim; ++j) {
for (int i = 0; i < nMethods; ++i) {
Interpolator1DDataBundle data = interp[i].getDataBundleFromSortedArrays(xValues[j], yValues[j]);
final double xMin = xValues[j][0];
final double xMax = xValues[j][nData - 1];
for (int m = 0; m < nKeys - 1; ++m) {
final double xKey = xMin + (xMax - xMin) * (m + 1.) / nKeys;
assertEquals(interp[i].firstDerivative(data, xKey), 0.5 * (interp[i].interpolate(data, xKey + EPS) - interp[i].interpolate(data, xKey - EPS)) / EPS, EPS);
}
}
}
}
/**
* Test for PiecewisePolynomialInterpolator1D
*/
@Test
public void piecewisePolynomialTest() {
final int nData = 10;
final int dim = 3;
final double[] xValues = new double[nData];
final double[][] yValues = new double[dim][nData];
final double[][] yValuesForClamped = new double[dim][nData + 2];
final int nKeys = 10 * nData;
final double[] xKeys = new double[nKeys];
for (int i = 0; i < nData; ++i) {
xValues[i] = i * i + i - 1.;
yValues[0][i] = 0.5 * xValues[i] * xValues[i] * xValues[i] - 1.5 * xValues[i] * xValues[i] + xValues[i] - 2.;
yValues[1][i] = Math.exp(0.1 * xValues[i] - 6.);
yValues[2][i] = (2. * xValues[i] * xValues[i] + xValues[i]) / (xValues[i] * xValues[i] + xValues[i] * xValues[i] * xValues[i] + 5. * xValues[i] + 2.);
yValuesForClamped[0][i + 1] = 0.5 * xValues[i] * xValues[i] * xValues[i] - 1.5 * xValues[i] * xValues[i] + xValues[i] - 2.;
yValuesForClamped[1][i + 1] = Math.exp(0.1 * xValues[i] - 6.);
yValuesForClamped[2][i + 1] = (2. * xValues[i] * xValues[i] + xValues[i]) / (xValues[i] * xValues[i] + xValues[i] * xValues[i] * xValues[i] + 5. * xValues[i] + 2.);
}
yValuesForClamped[0][0] = 0.;
yValuesForClamped[1][0] = 0.;
yValuesForClamped[2][0] = 0.;
yValuesForClamped[0][nData + 1] = 0.;
yValuesForClamped[1][nData + 1] = 0.;
yValuesForClamped[2][nData + 1] = 0.;
final double xMin = xValues[0];
final double xMax = xValues[nData - 1];
for (int i = 0; i < nKeys; ++i) {
xKeys[i] = xMin + (xMax - xMin) / (10 * nData - 1) * i;
}
final PiecewisePolynomialInterpolator[] bareInterp = new PiecewisePolynomialInterpolator[] {new CubicSplineInterpolator(), new ConstrainedCubicSplineInterpolator(),
new MonotonicityPreservingCubicSplineInterpolator(new NaturalSplineInterpolator()),
new MonotonicityPreservingQuinticSplineInterpolator(new NaturalSplineInterpolator()), new NaturalSplineInterpolator(),
new NonnegativityPreservingCubicSplineInterpolator(new NaturalSplineInterpolator()), new NonnegativityPreservingQuinticSplineInterpolator(new NaturalSplineInterpolator()),
new CubicSplineInterpolator(), new SemiLocalCubicSplineInterpolator(), new MonotoneConvexSplineInterpolator(), new ShapePreservingCubicSplineInterpolator() };
final Interpolator1D[] wrappedInterp = new PiecewisePolynomialInterpolator1D[] {new ClampedCubicSplineInterpolator1D(), new ConstrainedCubicSplineInterpolator1D(),
new MonotonicityPreservingCubicSplineInterpolator1D(), new MonotonicityPreservingQuinticSplineInterpolator1D(), new NaturalSplineInterpolator1D(),
new NonnegativityPreservingCubicSplineInterpolator1D(), new NonnegativityPreservingQuinticSplineInterpolator1D(), new NotAKnotCubicSplineInterpolator1D(),
new SemiLocalCubicSplineInterpolator1D(), new MonotoneConvexSplineInterpolator1D(), new ShapePreservingCubicSplineInterpolator1D() };
final int nMethods = bareInterp.length;
final PiecewisePolynomialFunction1D function = new PiecewisePolynomialFunction1D();
for (int i = 0; i < dim; ++i) {
final double[] bareResClamp = function.differentiate(bareInterp[0].interpolate(xValues, yValuesForClamped[i]), xKeys).getData()[0];
for (int j = 0; j < nKeys; ++j) {
final Interpolator1DDataBundle dataBundleClamp = wrappedInterp[0].getDataBundleFromSortedArrays(xValues, yValues[i]);
final double wrappedResClamp = wrappedInterp[0].firstDerivative(dataBundleClamp, xKeys[j]);
assertEquals(wrappedResClamp, bareResClamp[j], Math.max(Math.abs(bareResClamp[j]), 1.) * 1.e-15);
}
for (int k = 1; k < nMethods; ++k) {
final double[] bareRes = function.differentiate(bareInterp[k].interpolate(xValues, yValues[i]), xKeys).getData()[0];
for (int j = 0; j < nKeys; ++j) {
final Interpolator1DDataBundle dataBundle = wrappedInterp[k].getDataBundleFromSortedArrays(xValues, yValues[i]);
final double wrappedRes = wrappedInterp[k].firstDerivative(dataBundle, xKeys[j]);
assertEquals(wrappedRes, bareRes[j], Math.max(Math.abs(bareRes[j]), 1.) * 1.e-15);
}
}
}
}
/**
* Test for extrapolator
*/
@Test
public void firstDerivativeExtrapolatorstest() {
final double[][] xValues = new double[][] { {1., 2., 3., 4., 5., 6. }, {2., 2.1, 4., 5.1, 5.22, 6.8 } };
final double[][] yValues = new double[][] { {1., 1.1, 2., 3., 5.9, 6. }, {1., -1.1, 2.6, -3., -3.9, 3. } };
final int dim = xValues.length;
final Interpolator1D[] extrap = new Interpolator1D[] {new ExponentialExtrapolator1D(), new FlatExtrapolator1D(), new LinearExtrapolator1D(new PCHIPInterpolator1D()),
new CombinedInterpolatorExtrapolator(new PCHIPInterpolator1D(), new ExponentialExtrapolator1D(), new FlatExtrapolator1D()) };
final int nMethods = extrap.length;
final Interpolator1D interp = new PCHIPInterpolator1D();
for (int j = 0; j < dim; ++j) {
Interpolator1DDataBundle data = interp.getDataBundleFromSortedArrays(xValues[j], yValues[j]);
for (int i = 0; i < nMethods; ++i) {
// System.out.println(i);
if (i != 3) {
assertEquals(extrap[i].firstDerivative(data, .2), 0.5 * (extrap[i].interpolate(data, .2 + EPS) - extrap[i].interpolate(data, .2 - EPS)) / EPS, EPS);
}
assertEquals(extrap[i].firstDerivative(data, 7.2), 0.5 * (extrap[i].interpolate(data, 7.2 + EPS) - extrap[i].interpolate(data, 7.2 - EPS)) / EPS, EPS);
}
}
}
}