/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.math.impl.function;
import org.testng.annotations.Test;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.collect.array.DoubleMatrix;
import com.opengamma.strata.math.impl.differentiation.VectorFieldFirstOrderDifferentiator;
import com.opengamma.strata.math.impl.util.AssertMatrix;
/**
* Create a few {@link VectorFunction} (as anonymous inner classes) and check they concatenate correctly
*/
@Test
public class ConcatenatedVectorFunctionTest {
private static final VectorFieldFirstOrderDifferentiator DIFF = new VectorFieldFirstOrderDifferentiator();
private static final int NUM_FUNCS = 3;
private static final VectorFunction[] F = new VectorFunction[NUM_FUNCS];
private static final DoubleArray[] X = new DoubleArray[3];
private static final DoubleArray[] Y_EXP = new DoubleArray[3];
private static final DoubleMatrix[] JAC_EXP = new DoubleMatrix[3];
static {
F[0] = new VectorFunction() {
@Override
public DoubleArray apply(DoubleArray x) {
return DoubleArray.filled(1, x.get(0) + 2 * x.get(1));
}
@Override
public DoubleMatrix calculateJacobian(DoubleArray x) {
return DoubleMatrix.of(1, 2, 1d, 2d);
}
@Override
public int getLengthOfDomain() {
return 2;
}
@Override
public int getLengthOfRange() {
return 1;
}
};
F[1] = new VectorFunction() {
@Override
public DoubleArray apply(DoubleArray x) {
double x1 = x.get(0);
double x2 = x.get(1);
double y1 = x1 * x2;
double y2 = x2 * x2;
return DoubleArray.of(y1, y2);
}
@Override
public DoubleMatrix calculateJacobian(DoubleArray x) {
double x1 = x.get(0);
double x2 = x.get(1);
double j11 = x2;
double j12 = x1;
double j21 = 0.0;
double j22 = 2 * x2;
return DoubleMatrix.of(2, 2, j11, j12, j21, j22);
}
@Override
public int getLengthOfDomain() {
return 2;
}
@Override
public int getLengthOfRange() {
return 2;
}
};
F[2] = new VectorFunction() {
@Override
public DoubleArray apply(DoubleArray x) {
double x1 = x.get(0);
double y1 = x1;
double y2 = Math.sin(x1);
return DoubleArray.of(y1, y2);
}
@Override
public DoubleMatrix calculateJacobian(DoubleArray x) {
double x1 = x.get(0);
double j11 = 1.0;
double j21 = Math.cos(x1);
return DoubleMatrix.of(2, 1, j11, j21);
}
@Override
public int getLengthOfDomain() {
return 1;
}
@Override
public int getLengthOfRange() {
return 2;
}
};
X[0] = DoubleArray.of(-2., 2.);
X[1] = DoubleArray.of(1., 2.);
X[2] = DoubleArray.of(Math.PI);
Y_EXP[0] = DoubleArray.of(2.0);
Y_EXP[1] = DoubleArray.of(2.0, 4.0);
Y_EXP[2] = DoubleArray.of(Math.PI, 0.0);
JAC_EXP[0] = DoubleMatrix.of(1, 2, 1d, 2d);
JAC_EXP[1] = DoubleMatrix.of(2, 2, 2d, 1d, 0d, 4d);
JAC_EXP[2] = DoubleMatrix.of(2, 1, 1d, -1d);
}
/**
* /check individual functions first
*/
@Test
public void functionsTest() {
for (int i = 0; i < 3; i++) {
DoubleArray y = F[i].apply(X[i]);
DoubleMatrix jac = F[i].calculateJacobian(X[i]);
AssertMatrix.assertEqualsVectors(Y_EXP[i], y, 1e-15);
AssertMatrix.assertEqualsMatrix(JAC_EXP[i], jac, 1e-15);
}
}
@Test
public void conCatTest() {
DoubleArray cx = X[0].concat(X[1]).concat(X[2]);
DoubleArray cyExp = Y_EXP[0].concat(Y_EXP[1]).concat(Y_EXP[2]);
ConcatenatedVectorFunction cf = new ConcatenatedVectorFunction(F);
DoubleArray cy = cf.apply(cx);
AssertMatrix.assertEqualsVectors(cyExp, cy, 1e-15);
DoubleMatrix cJac = cf.calculateJacobian(cx);
DoubleMatrix fdJac = DIFF.differentiate(cf).apply(cx);
AssertMatrix.assertEqualsMatrix(fdJac, cJac, 1e-10);
}
}