/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.interpolation;
import static org.testng.AssertJUnit.assertEquals;
import java.util.TreeMap;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.analysis.solvers.BrentSolver;
import org.testng.annotations.Test;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.interpolation.data.ArrayInterpolator1DDataBundle;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle;
import com.opengamma.analytics.math.util.wrapper.CommonsMathWrapper;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class LogLinearWithSeasonalitiesInterpolator1DTest {
private static final int NB_MONTH = 12;
private static final double[] MONTHLY_FACTORS = {.01, .01, .01, .01, .01, .01, .01, .01, .01, .01, .01 };
private static final Interpolator1D STEP = new StepInterpolator1D();
private static final Interpolator1D INTERPOLATOR = new LogLinearWithSeasonalitiesInterpolator1D(MONTHLY_FACTORS);
private static final Function1D<Double, Double> FUNCTION = new Function1D<Double, Double>() {
@Override
public Double evaluate(final Double x) {
return 2 * x + 7;
}
};
private static final Interpolator1DDataBundle MODEL;
private static final Interpolator1DDataBundle TRANSFORMED_MODEL;
private static final double EPS = 1e-9;
static {
double sum = 0.0;
final double[] seasonalValues = new double[NB_MONTH];
for (int loopmonth = 0; loopmonth < NB_MONTH - 1; loopmonth++) {
seasonalValues[loopmonth] = MONTHLY_FACTORS[loopmonth];
sum = sum + MONTHLY_FACTORS[loopmonth];
}
seasonalValues[NB_MONTH - 1] = 1.0 - sum;
final TreeMap<Double, Double> data = new TreeMap<>();
final TreeMap<Double, Double> transformedData = new TreeMap<>();
double x;
for (int i = 0; i < 10; i++) {
x = Double.valueOf(i);
data.put(x, FUNCTION.evaluate(x));
}
MODEL = STEP.getDataBundle(data);
final double x1 = 3.0;
final double y1 = FUNCTION.evaluate(x1);
final double x2 = 4.0;
final double y2 = FUNCTION.evaluate(x2);
final double[] nodes = new double[NB_MONTH];
final double[] values = new double[NB_MONTH];
nodes[0] = x1;
values[0] = y1;
transformedData.put(nodes[0], values[0]);
// solver used to find the growth
final BrentSolver solver = new BrentSolver();
// definition of the function to minimize
final Function1D<Double, Double> function = new Function1D<Double, Double>() {
@Override
public Double evaluate(final Double xf) {
double result = y1;
for (int loopmonth = 0; loopmonth < NB_MONTH; loopmonth++) {
result = result * (1 + xf + seasonalValues[loopmonth]);
}
return result - y2;
}
};
// the initial guess for the solver is the solution when all seasonal values are set to 0.
final double initialGuess = Math.pow(y2 / y1, 1 / 12.0) - 1.0;
// We solve the equation define by the function and use the result to calculate values, nodes are also calculates.
final UnivariateRealFunction f = CommonsMathWrapper.wrapUnivariate(function);
double growth;
try {
growth = solver.solve(f, -.5, .5, initialGuess);
for (int loopmonth = 1; loopmonth < NB_MONTH; loopmonth++) {
values[loopmonth] = values[loopmonth - 1] * (1 + growth + seasonalValues[loopmonth]);
nodes[loopmonth] = x1 + loopmonth * (x2 - x1) / NB_MONTH;
transformedData.put(nodes[loopmonth], values[loopmonth]);
}
} catch (final MaxIterationsExceededException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (final FunctionEvaluationException ex) {
// TODO Auto-generated catch block`
ex.printStackTrace();
}
TRANSFORMED_MODEL = INTERPOLATOR.getDataBundle(transformedData);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullDataBundle() {
INTERPOLATOR.interpolate(null, 3.4);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullData() {
INTERPOLATOR.interpolate(MODEL, null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testLowValue() {
INTERPOLATOR.interpolate(MODEL, -2.);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testHighValue() {
INTERPOLATOR.interpolate(MODEL, 12.);
}
@Test
public void testDataBundleType1() {
assertEquals(INTERPOLATOR.getDataBundle(new double[] {1, 2, 3 }, new double[] {1, 2, 3 }).getClass(), ArrayInterpolator1DDataBundle.class);
}
@Test
public void testDataBundleType2() {
assertEquals(INTERPOLATOR.getDataBundleFromSortedArrays(new double[] {1, 2, 3 }, new double[] {1, 2, 3 }).getClass(), ArrayInterpolator1DDataBundle.class);
}
@Test
public void test() {
assertEquals(INTERPOLATOR.interpolate(MODEL, 3.9), STEP.interpolate(TRANSFORMED_MODEL, 3.9), EPS);
}
}