/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.minimization;
import static org.testng.Assert.assertEquals;
import java.util.BitSet;
import org.apache.commons.lang.Validate;
import org.testng.annotations.Test;
import com.opengamma.analytics.math.differentiation.VectorFieldFirstOrderDifferentiator;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.minimization.ParameterLimitsTransform.LimitType;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class NonLinearTransformFunctionTest {
private static final ParameterLimitsTransform[] NULL_TRANSFORMS;
private static final ParameterLimitsTransform[] TRANSFORMS;
private static final Function1D<DoubleMatrix1D, DoubleMatrix1D> FUNCTION = new Function1D<DoubleMatrix1D, DoubleMatrix1D>() {
@Override
public DoubleMatrix1D evaluate(DoubleMatrix1D x) {
Validate.isTrue(x.getNumberOfElements() == 2);
double x1 = x.getEntry(0);
double x2 = x.getEntry(1);
double[] y = new double[3];
y[0] = Math.sin(x1) * Math.cos(x2);
y[1] = Math.sin(x1) * Math.sin(x2);
y[2] = Math.cos(x1);
return new DoubleMatrix1D(y);
}
};
private static final Function1D<DoubleMatrix1D, DoubleMatrix2D> JACOBIAN = new Function1D<DoubleMatrix1D, DoubleMatrix2D>() {
@Override
public DoubleMatrix2D evaluate(DoubleMatrix1D x) {
Validate.isTrue(x.getNumberOfElements() == 2);
double x1 = x.getEntry(0);
double x2 = x.getEntry(1);
double[][] y = new double[3][2];
y[0][0] = Math.cos(x1) * Math.cos(x2);
y[0][1] = -Math.sin(x1) * Math.sin(x2);
y[1][0] = Math.cos(x1) * Math.sin(x2);
y[1][1] = Math.sin(x1) * Math.cos(x2);
y[2][0] = -Math.sin(x1);
y[2][1] = 0;
return new DoubleMatrix2D(y);
}
};
static {
NULL_TRANSFORMS = new ParameterLimitsTransform[2];
NULL_TRANSFORMS[0] = new NullTransform();
NULL_TRANSFORMS[1] = new NullTransform();
TRANSFORMS = new ParameterLimitsTransform[2];
TRANSFORMS[0] = new DoubleRangeLimitTransform(0, Math.PI);
TRANSFORMS[1] = new SingleRangeLimitTransform(0, LimitType.GREATER_THAN);
}
@Test
public void testNullTransform() {
BitSet fixed = new BitSet();
fixed.set(0);
DoubleMatrix1D start = new DoubleMatrix1D(new double[] {Math.PI / 4, 1 });
UncoupledParameterTransforms transforms = new UncoupledParameterTransforms(start, NULL_TRANSFORMS, fixed);
NonLinearTransformFunction transFunc = new NonLinearTransformFunction(FUNCTION, JACOBIAN, transforms);
Function1D<DoubleMatrix1D, DoubleMatrix1D> func = transFunc.getFittingFunction();
Function1D<DoubleMatrix1D, DoubleMatrix2D> jacFunc = transFunc.getFittingJacobian();
DoubleMatrix1D x = new DoubleMatrix1D(new double[] {0.5 });
final double rootHalf = Math.sqrt(0.5);
DoubleMatrix1D y = func.evaluate(x);
assertEquals(3, y.getNumberOfElements());
assertEquals(rootHalf * Math.cos(0.5), y.getEntry(0), 1e-9);
assertEquals(rootHalf * Math.sin(0.5), y.getEntry(1), 1e-9);
assertEquals(rootHalf, y.getEntry(2), 1e-9);
DoubleMatrix2D jac = jacFunc.evaluate(x);
assertEquals(3, jac.getNumberOfRows());
assertEquals(1, jac.getNumberOfColumns());
assertEquals(-rootHalf * Math.sin(0.5), jac.getEntry(0, 0), 1e-9);
assertEquals(rootHalf * Math.cos(0.5), jac.getEntry(1, 0), 1e-9);
assertEquals(0, jac.getEntry(2, 0), 1e-9);
}
@Test
public void testNonLinearTransform() {
BitSet fixed = new BitSet();
DoubleMatrix1D start = new DoubleMatrix1D(new double[2]);
UncoupledParameterTransforms transforms = new UncoupledParameterTransforms(start, TRANSFORMS, fixed);
NonLinearTransformFunction transFunc = new NonLinearTransformFunction(FUNCTION, JACOBIAN, transforms);
Function1D<DoubleMatrix1D, DoubleMatrix1D> func = transFunc.getFittingFunction();
Function1D<DoubleMatrix1D, DoubleMatrix2D> jacFunc = transFunc.getFittingJacobian();
VectorFieldFirstOrderDifferentiator diff = new VectorFieldFirstOrderDifferentiator();
Function1D<DoubleMatrix1D, DoubleMatrix2D> jacFuncFD = diff.differentiate(func);
DoubleMatrix1D testPoint = new DoubleMatrix1D(new double[] {4.5, -2.1 });
DoubleMatrix2D jac = jacFunc.evaluate(testPoint);
DoubleMatrix2D jacFD = jacFuncFD.evaluate(testPoint);
assertEquals(3, jac.getNumberOfRows());
assertEquals(2, jac.getNumberOfColumns());
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
assertEquals(jacFD.getEntry(i, j), jac.getEntry(i, j), 1e-6);
}
}
}
}