ShotgunDistance implements IDistanceMetric { @Override public double distance(final double[] a, final double[] b) { double totalDistance = 0; IVectorTransform transform; if (this.meanNormalization) { transform = new ZTransform(); } else { transform = new NormalizeByStdTransform(); } int numberOfDisjointWindows = a.length / this.windowLength; for (int i = 0; i < numberOfDisjointWindows; i++) { int startOfDisjointWindow = i * this.windowLength; double[] disjointWindow = Arrays.copyOfRange(a, startOfDisjointWindow, startOfDisjointWindow + this.windowLength); disjointWindow = transform.transform(disjointWindow); double windowDistance = Double.MAX_VALUE; int numberOfSlidingWindows = b.length - this.windowLength + 1; for (int j = 0; j < numberOfSlidingWindows; j++) { int startOfSlidingWindow = j; double[] slidingWindow = Arrays.copyOfRange(b, startOfSlidingWindow, startOfSlidingWindow + this.windowLength); slidingWindow = transform.transform(slidingWindow); double distanceDisjointSliding = this.euclideanDistance.distance(disjointWindow, slidingWindow); if (distanceDisjointSliding < windowDistance) { windowDistance = distanceDisjointSliding; } } totalDistance += windowDistance; } return totalDistance; } ShotgunDistance(final int windowLength, final boolean meanNormalization); @Override double distance(final double[] a, final double[] b); void setWindowLength(final int windowLength);  }
@Test public void testCorrectnessForDistanceCalculation() { double[] queryTimeSeries = { 1, 1, 2, 2, 3, 5, 3 }; double[] sampleTimeSeries = { 1, 2, 3, 5, 5, 7 }; double expectation = 0; int windowLength = 2; boolean meanNormalization = false; ShotgunDistance shotgunDistance = new ShotgunDistance(windowLength, meanNormalization); double distance = shotgunDistance.distance(queryTimeSeries, sampleTimeSeries); assertEquals(expectation, distance, 1e-5); }
@Test public void testCorrectnessForDistanceCalculation2() { double[] queryTimeSeries = { 1, 1, 2, 2, 3, 5, 3 }; double[] sampleTimeSeries = { 1, 2, 3, 5, 5, 7 }; double expectation = .635109; int windowLength = 3; boolean meanNormalization = false; ShotgunDistance shotgunDistance = new ShotgunDistance(windowLength, meanNormalization); double distance = shotgunDistance.distance(queryTimeSeries, sampleTimeSeries); assertEquals(expectation, distance, 1e-5); }
@Test public void testRobustnessForTooLongWindowLength() { double[] queryTimeSeries = { 1, 2, 3 }; double[] sampleTimeSeries = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; int windowLength = 5; ShotgunDistance shotgunDistance = new ShotgunDistance(windowLength, false); shotgunDistance.distance(queryTimeSeries, sampleTimeSeries); assertTrue(true); }
@Test public void testRobustnessForTooLongWindowLength2() { double[] queryTimeSeries = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; double[] sampleTimeSeries = { 1, 2, 3 }; int windowLength = 5; ShotgunDistance shotgunDistance = new ShotgunDistance(windowLength, false); shotgunDistance.distance(queryTimeSeries, sampleTimeSeries); assertTrue(true); }
@Test public void testRobustnessForTooLongWindowLength3() { double[] queryTimeSeries = { 1, 2, 3 }; double[] sampleTimeSeries = { 1, 1, 1 }; int windowLength = 5; ShotgunDistance shotgunDistance = new ShotgunDistance(windowLength, false); shotgunDistance.distance(queryTimeSeries, sampleTimeSeries); assertTrue(true); }