/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.math.impl.differentiation; import static org.testng.Assert.assertTrue; import static org.testng.AssertJUnit.assertEquals; import java.util.function.Function; import org.testng.annotations.Test; import com.opengamma.strata.collect.DoubleArrayMath; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.collect.array.DoubleMatrix; /** * Test. */ @Test public class VectorFieldSecondOrderDifferentiatorTest { private static Function<DoubleArray, DoubleArray> FUNC = new Function<DoubleArray, DoubleArray>() { @Override public DoubleArray apply(DoubleArray x) { double a = x.get(0); double theta = x.get(1); double c1 = Math.cos(theta); return DoubleArray.of(a * c1 * c1, a * (1 - c1 * c1)); } }; private static Function<DoubleArray, Boolean> DOMAIN = new Function<DoubleArray, Boolean>() { @Override public Boolean apply(DoubleArray x) { double a = x.get(0); double theta = x.get(1); if (a <= 0) { return false; } if (theta < 0.0 || theta > Math.PI) { return false; } return true; } }; private static Function<DoubleArray, DoubleMatrix> DW1 = new Function<DoubleArray, DoubleMatrix>() { @Override public DoubleMatrix apply(DoubleArray x) { double a = x.get(0); double theta = x.get(1); double[][] temp = new double[2][2]; double c1 = Math.cos(theta); double s1 = Math.sin(theta); temp[0][0] = 0.0; temp[1][1] = 2 * a * (1 - 2 * c1 * c1); temp[0][1] = -2 * s1 * c1; temp[1][0] = temp[0][1]; return DoubleMatrix.copyOf(temp); } }; private static Function<DoubleArray, DoubleMatrix> DW2 = new Function<DoubleArray, DoubleMatrix>() { @Override public DoubleMatrix apply(DoubleArray x) { double a = x.get(0); double theta = x.get(1); double[][] temp = new double[2][2]; double c1 = Math.cos(theta); double s1 = Math.sin(theta); temp[0][0] = 0.0; temp[1][1] = 2 * a * (2 * c1 * c1 - 1); temp[0][1] = 2 * s1 * c1; temp[1][0] = temp[0][1]; return DoubleMatrix.copyOf(temp); } }; @Test public void test() { double a = 2.3; double theta = 0.34; DoubleArray x = DoubleArray.of(a, theta); VectorFieldSecondOrderDifferentiator fd = new VectorFieldSecondOrderDifferentiator(); Function<DoubleArray, DoubleMatrix[]> fdFuncs = fd.differentiate(FUNC); DoubleMatrix[] fdValues = fdFuncs.apply(x); DoubleMatrix t1 = DW1.apply(x); DoubleMatrix t2 = DW2.apply(x); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { assertEquals("first observation " + i + " " + j, t1.get(i, j), fdValues[0].get(i, j), 1e-6); assertEquals("second observation " + i + " " + j, t2.get(i, j), fdValues[1].get(i, j), 1e-6); } } } @Test(expectedExceptions = IllegalArgumentException.class) public void outsideDomainTest() { VectorFieldSecondOrderDifferentiator fd = new VectorFieldSecondOrderDifferentiator(); Function<DoubleArray, DoubleMatrix[]> fdFuncs = fd.differentiate(FUNC, DOMAIN); fdFuncs.apply(DoubleArray.of(-1.0, 0.3)); } @Test public void domainTest() { DoubleArray[] x = new DoubleArray[4]; x[0] = DoubleArray.of(2.3, 0.34); x[1] = DoubleArray.of(1e-8, 1.45); x[2] = DoubleArray.of(1.2, 0.0); x[3] = DoubleArray.of(1.2, Math.PI); VectorFieldSecondOrderDifferentiator fd = new VectorFieldSecondOrderDifferentiator(); Function<DoubleArray, DoubleMatrix[]> fdFuncs = fd.differentiate(FUNC, DOMAIN); for (int k = 0; k < 4; k++) { DoubleMatrix[] fdValues = fdFuncs.apply(x[k]); DoubleMatrix t1 = DW1.apply(x[k]); DoubleMatrix t2 = DW2.apply(x[k]); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { assertEquals("first observation " + i + " " + j, t1.get(i, j), fdValues[0].get(i, j), 1e-6); assertEquals("second observation " + i + " " + j, t2.get(i, j), fdValues[1].get(i, j), 1e-6); } } } } @Test public void tes_differentiateNoCrosst() { Function<DoubleArray, DoubleArray> func = new Function<DoubleArray, DoubleArray>() { @Override public DoubleArray apply(DoubleArray x) { double x1 = x.get(0); double x2 = x.get(1); return DoubleArray.of(x1 * x1 * x1 + x2 * x2, Math.exp(1.5 * x1), Math.log(2d * x1) * Math.sin(x2)); } }; double[][] keys = new double[][] { {1.5, -2.1 }, {2.3445, 0.5 } }; Function<DoubleArray, DoubleMatrix> funcExp = new Function<DoubleArray, DoubleMatrix>() { @Override public DoubleMatrix apply(DoubleArray x) { double x1 = x.get(0); double x2 = x.get(1); double[][] mat = new double[][] { {6d * x1, 2.25 * Math.exp(1.5 * x1), -Math.sin(x2) / x1 / x1 }, {2d, 0d, -Math.log(2d * x1) * Math.sin(x2) } }; return DoubleMatrix.ofUnsafe(mat); } }; VectorFieldSecondOrderDifferentiator fd = new VectorFieldSecondOrderDifferentiator(); Function<DoubleArray, DoubleMatrix> fdFuncs = fd.differentiateNoCross(func); for (double[] key : keys) { DoubleMatrix cmp = fdFuncs.apply(DoubleArray.ofUnsafe(key)); DoubleMatrix exp = funcExp.apply(DoubleArray.ofUnsafe(key)); assertTrue(DoubleArrayMath.fuzzyEquals(cmp.column(0).toArray(), exp.row(0).toArray(), 1.0e-5)); assertTrue(DoubleArrayMath.fuzzyEquals(cmp.column(1).toArray(), exp.row(1).toArray(), 1.0e-5)); } } }