VectorFieldFirstOrderDifferentiator implements Differentiator<DoubleMatrix1D, DoubleMatrix1D, DoubleMatrix2D> { @Override public Function1D<DoubleMatrix1D, DoubleMatrix2D> differentiate(final Function1D<DoubleMatrix1D, DoubleMatrix1D> function) { Validate.notNull(function); switch (_differenceType) { case FORWARD: return new Function1D<DoubleMatrix1D, DoubleMatrix2D>() { @SuppressWarnings("synthetic-access") @Override public DoubleMatrix2D evaluate(final DoubleMatrix1D x) { Validate.notNull(x, "x"); final DoubleMatrix1D y = function.evaluate(x); final int n = x.getNumberOfElements(); final int m = y.getNumberOfElements(); final double[] xData = x.getData(); double oldValue; final double[][] res = new double[m][n]; int i, j; DoubleMatrix1D up; for (j = 0; j < n; j++) { oldValue = xData[j]; xData[j] += _eps; up = function.evaluate(x); for (i = 0; i < m; i++) { res[i][j] = (up.getEntry(i) - y.getEntry(i)) / _eps; } xData[j] = oldValue; } return new DoubleMatrix2D(res); } }; case CENTRAL: return new Function1D<DoubleMatrix1D, DoubleMatrix2D>() { @SuppressWarnings("synthetic-access") @Override public DoubleMatrix2D evaluate(final DoubleMatrix1D x) { Validate.notNull(x, "x"); final DoubleMatrix1D y = function.evaluate(x); final int n = x.getNumberOfElements(); final int m = y.getNumberOfElements(); final double[] xData = x.getData(); double oldValue; final double[][] res = new double[m][n]; int i, j; DoubleMatrix1D up, down; for (j = 0; j < n; j++) { oldValue = xData[j]; xData[j] += _eps; up = function.evaluate(x); xData[j] -= _twoEps; down = function.evaluate(x); for (i = 0; i < m; i++) { res[i][j] = (up.getEntry(i) - down.getEntry(i)) / _twoEps; } xData[j] = oldValue; } return new DoubleMatrix2D(res); } }; case BACKWARD: return new Function1D<DoubleMatrix1D, DoubleMatrix2D>() { @SuppressWarnings("synthetic-access") @Override public DoubleMatrix2D evaluate(final DoubleMatrix1D x) { Validate.notNull(x, "x"); final DoubleMatrix1D y = function.evaluate(x); final int n = x.getNumberOfElements(); final int m = y.getNumberOfElements(); final double[] xData = x.getData(); double oldValue; final double[][] res = new double[m][n]; int i, j; DoubleMatrix1D down; for (j = 0; j < n; j++) { oldValue = xData[j]; xData[j] -= _eps; down = function.evaluate(x); for (i = 0; i < m; i++) { res[i][j] = (y.getEntry(i) - down.getEntry(i)) / _eps; } xData[j] = oldValue; } return new DoubleMatrix2D(res); } }; default: throw new IllegalArgumentException("Can only handle forward, backward and central differencing"); } } VectorFieldFirstOrderDifferentiator();  VectorFieldFirstOrderDifferentiator(final FiniteDifferenceType differenceType);  VectorFieldFirstOrderDifferentiator(final FiniteDifferenceType differenceType, final double eps);  VectorFieldFirstOrderDifferentiator(final double eps); @Override Function1D<DoubleMatrix1D, DoubleMatrix2D> differentiate(final Function1D<DoubleMatrix1D, DoubleMatrix1D> function); @Override Function1D<DoubleMatrix1D, DoubleMatrix2D> differentiate(final Function1D<DoubleMatrix1D, DoubleMatrix1D> function, final Function1D<DoubleMatrix1D, Boolean> domain);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullFunction() { CENTRAL.differentiate((Function1D<DoubleMatrix1D, DoubleMatrix1D>) null); }
@Test public void test() { final DoubleMatrix1D x = new DoubleMatrix1D(new double[] {.2245, -1.2344 }); final DoubleMatrix2D anJac = G.evaluate(x); final DoubleMatrix2D fdFwdJac = FORWARD.differentiate(F).evaluate(x); final DoubleMatrix2D fdCentGrad = CENTRAL.differentiate(F).evaluate(x); final DoubleMatrix2D fdBackGrad = BACKWARD.differentiate(F).evaluate(x); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { assertEquals(fdFwdJac.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS); assertEquals(fdCentGrad.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS * EPS); assertEquals(fdBackGrad.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS); } } }
@Test public void test2() { final DoubleMatrix1D x = new DoubleMatrix1D(new double[] {1.3423, 0.235 }); final DoubleMatrix2D anJac = G2.evaluate(x); final DoubleMatrix2D fdFwdJac = FORWARD.differentiate(F2).evaluate(x); final DoubleMatrix2D fdCentGrad = CENTRAL.differentiate(F2).evaluate(x); final DoubleMatrix2D fdBackGrad = BACKWARD.differentiate(F2).evaluate(x); for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { assertEquals(fdFwdJac.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS); assertEquals(fdCentGrad.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS * EPS); assertEquals(fdBackGrad.getEntry(i, j), anJac.getEntry(i, j), 10 * EPS); } } }
@Test(expectedExceptions = IllegalArgumentException.class) public void outsideDomainTest() { final Function1D<DoubleMatrix1D, DoubleMatrix2D> fdJacFunc = CENTRAL.differentiate(F2, DOMAIN); fdJacFunc.evaluate(new DoubleMatrix1D(2.3, 3.2)); }
@Test public void testDomain() { final DoubleMatrix1D[] x = new DoubleMatrix1D[7]; x[0] = new DoubleMatrix1D(new double[] {1.3423, 0.235 }); x[1] = new DoubleMatrix1D(new double[] {0.0, 1.235 }); x[2] = new DoubleMatrix1D(new double[] {Math.PI, 3.1 }); x[3] = new DoubleMatrix1D(new double[] {2.3, 0.0 }); x[4] = new DoubleMatrix1D(new double[] {2.3, Math.PI }); x[5] = new DoubleMatrix1D(new double[] {0.0, 0.0 }); x[6] = new DoubleMatrix1D(new double[] {Math.PI, Math.PI }); final Function1D<DoubleMatrix1D, DoubleMatrix2D> fdJacFunc = CENTRAL.differentiate(F2, DOMAIN); for (int k = 0; k < 7; k++) { final DoubleMatrix2D anJac = G2.evaluate(x[k]); final DoubleMatrix2D fdJac = fdJacFunc.evaluate(x[k]); for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { assertEquals("set " + k, anJac.getEntry(i, j), fdJac.getEntry(i, j), 1e-8); } } } }