TimeWarpEditDistance implements ITimeseriesDistanceMetric { @Override public double distance(final double[] a, final double[] tA, final double[] b, final double[] tB) { int n = a.length; int m = b.length; double[][] dp = new double[n + 1][m + 1]; for (int i = 1; i <= n; i++) { dp[i][0] = Double.MAX_VALUE; } for (int i = 1; i <= m; i++) { dp[0][i] = Double.MAX_VALUE; } dp[0][0] = 0d; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { double c1; double c2; double c3; if (i == 1 && j == 1) { c1 = dp[i - 1][j] + this.d.distance(0, a[i - 1]) + this.nu * tA[i - 1] + this.lambda; c2 = dp[i][j - 1] + this.d.distance(0, b[j - 1]) + this.nu * tB[j - 1] + this.lambda; c3 = dp[i - 1][j - 1] + this.d.distance(a[i - 1], b[i - 1]) + this.nu * Math.abs(tA[i - 1] - tB[j - 1]); } else if (i == 1) { c1 = dp[i - 1][j] + this.d.distance(0, a[i - 1]) + this.nu * tA[i - 1] + this.lambda; c2 = dp[i][j - 1] + this.d.distance(b[j - 2], b[j - 1]) + this.nu * (tB[j - 1] - tB[j - 2]) + this.lambda; c3 = dp[i - 1][j - 1] + this.d.distance(a[i - 1], b[i - 1]) + this.d.distance(0, b[j - 2]) + this.nu * (Math.abs(tA[i - 1] - tB[j - 1]) + tB[j - 2]); } else if (j == 1) { c1 = dp[i - 1][j] + this.d.distance(a[i - 2], a[i - 1]) + this.nu * (tA[i - 1] - tA[i - 2]) + this.lambda; c2 = dp[i][j - 1] + this.d.distance(0, b[j - 1]) + this.nu * tB[j - 1] + this.lambda; c3 = dp[i - 1][j - 1] + this.d.distance(a[i - 1], b[i - 1]) + this.d.distance(a[i - 2], 0) + this.nu * (Math.abs(tA[i - 1] - tB[j - 1]) + tA[i - 2]); } else { c1 = dp[i - 1][j] + this.d.distance(a[i - 2], a[i - 1]) + this.nu * (tA[i - 1] - tA[i - 2]) + this.lambda; c2 = dp[i][j - 1] + this.d.distance(b[j - 2], b[j - 1]) + this.nu * (tB[j - 1] - tB[j - 2]) + this.lambda; c3 = dp[i - 1][j - 1] + this.d.distance(a[i - 1], b[i - 1]) + this.d.distance(a[i - 2], b[j - 2]) + this.nu * (Math.abs(tA[i - 1] - tB[j - 1]) + Math.abs(tA[i - 2] - tB[j - 2])); } double minimum = Math.min(c1, Math.min(c2, c3)); dp[i][j] = minimum; } } return dp[n][m]; } TimeWarpEditDistance(final double lambda, final double nu, final IScalarDistance d);  TimeWarpEditDistance(final double lambda, final double nu); @Override double distance(final double[] a, final double[] tA, final double[] b, final double[] tB);  }
@Test public void testCorrectnessForDistanceCalculation() { double[] timeSeries1 = { 1, 1, 1, 1, 1, 1 }; double[] timeSeries2 = { 1, 1, 1, 1, 1, 1 }; double expectation = 0; double lambda = 1.0; double nu = 0.001; TimeWarpEditDistance twed = new TimeWarpEditDistance(lambda, nu); double distance = twed.distance(timeSeries1, timeSeries2); assertEquals(expectation, distance, 0); }
@Test public void testCorrectnessForDistanceCalculation2() { double[] timeSeries1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; double[] timeSeries2 = { 1, 2, 3, 4, 5, 6, 7, 8, 12 }; double expectation = 3; double lambda = 1.0; double nu = 0.001; IScalarDistance d = ScalarDistanceUtil.getAbsoluteDistance(); TimeWarpEditDistance twed = new TimeWarpEditDistance(lambda, nu, d); double distance = twed.distance(timeSeries1, timeSeries2); assertEquals(expectation, distance, 0); }
@Test public void testDistanceCalculation3() { double[] timeSeries1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; double[] timeSeries2 = { 0, 3, 2, 5, 4, 7, 6, 9, 8 }; double expectation = 17; double lambda = 1.0; double nu = 0.001; IScalarDistance d = ScalarDistanceUtil.getAbsoluteDistance(); TimeWarpEditDistance twed = new TimeWarpEditDistance(lambda, nu, d); double distance = twed.distance(timeSeries1, timeSeries2); assertEquals(expectation, distance, 0); }