/**
* Copyright (C) 2009 - 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.AssertJUnit.assertEquals;
import java.util.function.Function;
import org.testng.annotations.Test;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.collect.array.DoubleMatrix;
/**
* Test.
*/
@Test
public class VectorFieldFirstOrderDifferentiatorTest {
private static final Function<DoubleArray, DoubleArray> F = new Function<DoubleArray, DoubleArray>() {
@Override
public DoubleArray apply(final DoubleArray x) {
double x1 = x.get(0);
double x2 = x.get(1);
return DoubleArray.of(
x1 * x1 + 2 * x2 * x2 - x1 * x2 + x1 * Math.cos(x2) - x2 * Math.sin(x1),
2 * x1 * x2 * Math.cos(x1 * x2) - x1 * Math.sin(x1) - x2 * Math.cos(x2));
}
};
private static final Function<DoubleArray, DoubleArray> F2 = new Function<DoubleArray, DoubleArray>() {
@Override
public DoubleArray apply(final DoubleArray x) {
double x1 = x.get(0);
double x2 = x.get(1);
return DoubleArray.of(
x1 * x1 + 2 * x2 * x2 - x1 * x2 + x1 * Math.cos(x2) - x2 * Math.sin(x1),
2 * x1 * x2 * Math.cos(x1 * x2) - x1 * Math.sin(x1) - x2 * Math.cos(x2),
x1 - x2);
}
};
private static final Function<DoubleArray, DoubleMatrix> G = new Function<DoubleArray, DoubleMatrix>() {
@Override
public DoubleMatrix apply(final DoubleArray x) {
final double x1 = x.get(0);
final double x2 = x.get(1);
final double[][] jac = new double[2][2];
jac[0][0] = 2 * x1 - x2 + Math.cos(x2) - x2 * Math.cos(x1);
jac[0][1] = 4 * x2 - x1 - x1 * Math.sin(x2) - Math.sin(x1);
jac[1][0] = 2 * x2 * Math.cos(x1 * x2) - 2 * x1 * x2 * x2 * Math.sin(x1 * x2) - Math.sin(x1) - x1 * Math.cos(x1);
jac[1][1] = 2 * x1 * Math.cos(x1 * x2) - 2 * x1 * x1 * x2 * Math.sin(x1 * x2) - Math.cos(x2) + x2 * Math.sin(x2);
return DoubleMatrix.copyOf(jac);
}
};
private static final Function<DoubleArray, DoubleMatrix> G2 = new Function<DoubleArray, DoubleMatrix>() {
@Override
public DoubleMatrix apply(final DoubleArray x) {
final double x1 = x.get(0);
final double x2 = x.get(1);
final double[][] jac = new double[3][2];
jac[0][0] = 2 * x1 - x2 + Math.cos(x2) - x2 * Math.cos(x1);
jac[0][1] = 4 * x2 - x1 - x1 * Math.sin(x2) - Math.sin(x1);
jac[1][0] = 2 * x2 * Math.cos(x1 * x2) - 2 * x1 * x2 * x2 * Math.sin(x1 * x2) - Math.sin(x1) - x1 * Math.cos(x1);
jac[1][1] = 2 * x1 * Math.cos(x1 * x2) - 2 * x1 * x1 * x2 * Math.sin(x1 * x2) - Math.cos(x2) + x2 * Math.sin(x2);
jac[2][0] = 1;
jac[2][1] = -1;
return DoubleMatrix.copyOf(jac);
}
};
private static final Function<DoubleArray, Boolean> DOMAIN = new Function<DoubleArray, Boolean>() {
@Override
public Boolean apply(final DoubleArray x) {
final double x1 = x.get(0);
final double x2 = x.get(1);
if (x1 < 0 || x1 > Math.PI || x2 < 0 || x2 > Math.PI) {
return false;
}
return true;
}
};
private static final double EPS = 1e-5;
private static final VectorFieldFirstOrderDifferentiator FORWARD = new VectorFieldFirstOrderDifferentiator(FiniteDifferenceType.FORWARD, EPS);
private static final VectorFieldFirstOrderDifferentiator CENTRAL = new VectorFieldFirstOrderDifferentiator(FiniteDifferenceType.CENTRAL, EPS);
private static final VectorFieldFirstOrderDifferentiator BACKWARD = new VectorFieldFirstOrderDifferentiator(FiniteDifferenceType.BACKWARD, EPS);
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullDifferenceType() {
new ScalarFirstOrderDifferentiator(null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullFunction() {
CENTRAL.differentiate((Function<DoubleArray, DoubleArray>) null);
}
@Test
public void test() {
final DoubleArray x = DoubleArray.of(.2245, -1.2344);
final DoubleMatrix anJac = G.apply(x);
final DoubleMatrix fdFwdJac = FORWARD.differentiate(F).apply(x);
final DoubleMatrix fdCentGrad = CENTRAL.differentiate(F).apply(x);
final DoubleMatrix fdBackGrad = BACKWARD.differentiate(F).apply(x);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
assertEquals(fdFwdJac.get(i, j), anJac.get(i, j), 10 * EPS);
assertEquals(fdCentGrad.get(i, j), anJac.get(i, j), 10 * EPS * EPS);
assertEquals(fdBackGrad.get(i, j), anJac.get(i, j), 10 * EPS);
}
}
}
@Test
public void test2() {
final DoubleArray x = DoubleArray.of(1.3423, 0.235);
final DoubleMatrix anJac = G2.apply(x);
final DoubleMatrix fdFwdJac = FORWARD.differentiate(F2).apply(x);
final DoubleMatrix fdCentGrad = CENTRAL.differentiate(F2).apply(x);
final DoubleMatrix fdBackGrad = BACKWARD.differentiate(F2).apply(x);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
assertEquals(fdFwdJac.get(i, j), anJac.get(i, j), 10 * EPS);
assertEquals(fdCentGrad.get(i, j), anJac.get(i, j), 10 * EPS * EPS);
assertEquals(fdBackGrad.get(i, j), anJac.get(i, j), 10 * EPS);
}
}
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void outsideDomainTest() {
final Function<DoubleArray, DoubleMatrix> fdJacFunc = CENTRAL.differentiate(F2, DOMAIN);
fdJacFunc.apply(DoubleArray.of(2.3, 3.2));
}
@Test
public void testDomain() {
final DoubleArray[] x = new DoubleArray[7];
x[0] = DoubleArray.of(1.3423, 0.235);
x[1] = DoubleArray.of(0.0, 1.235);
x[2] = DoubleArray.of(Math.PI, 3.1);
x[3] = DoubleArray.of(2.3, 0.0);
x[4] = DoubleArray.of(2.3, Math.PI);
x[5] = DoubleArray.of(0.0, 0.0);
x[6] = DoubleArray.of(Math.PI, Math.PI);
final Function<DoubleArray, DoubleMatrix> fdJacFunc = CENTRAL.differentiate(F2, DOMAIN);
for (int k = 0; k < 7; k++) {
final DoubleMatrix anJac = G2.apply(x[k]);
final DoubleMatrix fdJac = fdJacFunc.apply(x[k]);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
assertEquals("set " + k, anJac.get(i, j), fdJac.get(i, j), 1e-8);
}
}
}
}
}