/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.function;
import org.testng.annotations.Test;
import com.opengamma.analytics.math.differentiation.VectorFieldFirstOrderDifferentiator;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.util.AssertMatrix;
import com.opengamma.util.test.TestGroup;
/**
* Create a few {@link VectorFunction} (as anonymous inner classes) and check they concatenate correctly
*/
@Test(groups = TestGroup.UNIT)
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 DoubleMatrix1D[] X = new DoubleMatrix1D[3];
private static final DoubleMatrix1D[] Y_EXP = new DoubleMatrix1D[3];
private static final DoubleMatrix2D[] JAC_EXP = new DoubleMatrix2D[3];
static {
F[0] = new VectorFunction() {
@Override
public DoubleMatrix1D evaluate(final DoubleMatrix1D x) {
return new DoubleMatrix1D(1, x.getEntry(0) + 2 * x.getEntry(1));
}
@Override
public DoubleMatrix2D calculateJacobian(final DoubleMatrix1D x) {
final DoubleMatrix2D jac = new DoubleMatrix2D(1, 2);
jac.getData()[0][0] = 1.0;
jac.getData()[0][1] = 2.0;
return jac;
}
@Override
public int getLengthOfDomain() {
return 2;
}
@Override
public int getLengthOfRange() {
return 1;
}
};
F[1] = new VectorFunction() {
@Override
public DoubleMatrix1D evaluate(final DoubleMatrix1D x) {
final double x1 = x.getEntry(0);
final double x2 = x.getEntry(1);
final double y1 = x1 * x2;
final double y2 = x2 * x2;
return new DoubleMatrix1D(y1, y2);
}
@Override
public DoubleMatrix2D calculateJacobian(final DoubleMatrix1D x) {
final double x1 = x.getEntry(0);
final double x2 = x.getEntry(1);
final double j11 = x2;
final double j12 = x1;
final double j21 = 0.0;
final double j22 = 2 * x2;
return new DoubleMatrix2D(new double[][] { {j11, j12 }, {j21, j22 } });
}
@Override
public int getLengthOfDomain() {
return 2;
}
@Override
public int getLengthOfRange() {
return 2;
}
};
F[2] = new VectorFunction() {
@Override
public DoubleMatrix1D evaluate(final DoubleMatrix1D x) {
final double x1 = x.getEntry(0);
final double y1 = x1;
final double y2 = Math.sin(x1);
return new DoubleMatrix1D(y1, y2);
}
@Override
public DoubleMatrix2D calculateJacobian(final DoubleMatrix1D x) {
final double x1 = x.getEntry(0);
final double j11 = 1.0;
final double j21 = Math.cos(x1);
return new DoubleMatrix2D(new double[][] { {j11 }, {j21 } });
}
@Override
public int getLengthOfDomain() {
return 1;
}
@Override
public int getLengthOfRange() {
return 2;
}
};
X[0] = new DoubleMatrix1D(-2., 2.);
X[1] = new DoubleMatrix1D(1., 2.);
X[2] = new DoubleMatrix1D(Math.PI);
Y_EXP[0] = new DoubleMatrix1D(2.0);
Y_EXP[1] = new DoubleMatrix1D(2.0, 4.0);
Y_EXP[2] = new DoubleMatrix1D(Math.PI, 0.0);
JAC_EXP[0] = new DoubleMatrix2D(new double[][] {{1.0, 2.0 } });
JAC_EXP[1] = new DoubleMatrix2D(new double[][] { {2.0, 1.0 }, {0.0, 4.0 } });
JAC_EXP[2] = new DoubleMatrix2D(new double[][] { {1.0 }, {-1.0 } });
}
/**
* /check individual functions first
*/
@Test
public void functionsTest() {
for (int i = 0; i < 3; i++) {
final DoubleMatrix1D y = F[i].evaluate(X[i]);
final DoubleMatrix2D 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() {
final DoubleMatrix1D cx = conCat(X);
final DoubleMatrix1D cyExp = conCat(Y_EXP);
final ConcatenatedVectorFunction cf = new ConcatenatedVectorFunction(F);
final DoubleMatrix1D cy = cf.evaluate(cx);
AssertMatrix.assertEqualsVectors(cyExp, cy, 1e-15);
final DoubleMatrix2D cJac = cf.calculateJacobian(cx);
final DoubleMatrix2D fdJac = DIFF.differentiate(cf).evaluate(cx);
AssertMatrix.assertEqualsMatrix(fdJac, cJac, 1e-10);
}
private DoubleMatrix1D conCat(final DoubleMatrix1D[] x) {
final int n = x.length;
int pos = 0;
for (int i = 0; i < n; i++) {
pos += x[i].getNumberOfElements();
}
final DoubleMatrix1D res = new DoubleMatrix1D(pos);
pos = 0;
for (int i = 0; i < n; i++) {
final int m = x[i].getNumberOfElements();
System.arraycopy(x[i].getData(), 0, res.getData(), pos, m);
pos += m;
}
return res;
}
}