diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java | 128 |
1 files changed, 99 insertions, 29 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java index 186f0435..b419f0df 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java @@ -40,52 +40,122 @@ public class WeightedManhattanDistanceFunction extends WeightedLPNormDistanceFun * @param weights Weight vector */ public WeightedManhattanDistanceFunction(double[] weights) { - super(1.0, weights); + super(1., weights); } - @Override - public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) { - final int dim = dimensionality(v1, v2, weights.length); - double agg = 0; - for (int d = 0; d < dim; d++) { - final double delta = Math.abs(v1.doubleValue(d) - v2.doubleValue(d)); + private final double doublePreDistance(NumberVector<?> v1, NumberVector<?> v2, final int start, final int end, double agg) { + for (int d = start; d < end; d++) { + final double xd = v1.doubleValue(d), yd = v2.doubleValue(d); + final double delta = (xd >= yd) ? xd - yd : yd - xd; agg += delta * weights[d]; } return agg; } - @Override - public double doubleNorm(NumberVector<?> v) { - final int dim = v.getDimensionality(); - double agg = 0; - for (int d = 0; d < dim; d++) { - final double delta = Math.abs(v.doubleValue(d)); + private final double doublePreDistanceVM(NumberVector<?> v, SpatialComparable mbr, final int start, final int end, double agg) { + for (int d = start; d < end; d++) { + final double value = v.doubleValue(d), min = mbr.getMin(d); + double delta = min - value; + if (delta < 0.) { + delta = value - mbr.getMax(d); + } + if (delta > 0.) { + agg += delta * weights[d]; + } + } + return agg; + } + + private final double doublePreDistanceMBR(SpatialComparable mbr1, SpatialComparable mbr2, final int start, final int end, double agg) { + for (int d = start; d < end; d++) { + double delta = mbr2.getMin(d) - mbr1.getMax(d); + if (delta < 0.) { + delta = mbr1.getMin(d) - mbr2.getMax(d); + } + if (delta > 0.) { + agg += delta * weights[d]; + } + } + return agg; + } + + private final double doublePreNorm(NumberVector<?> v, final int start, final int end, double agg) { + for (int d = start; d < end; d++) { + final double xd = v.doubleValue(d); + final double delta = xd >= 0. ? xd : -xd; agg += delta * weights[d]; } return agg; } + private final double doublePreNormMBR(SpatialComparable mbr, final int start, final int end, double agg) { + for (int d = start; d < end; d++) { + double delta = mbr.getMin(d); + if (delta < 0.) { + delta = -mbr.getMax(d); + } + if (delta > 0.) { + agg += delta * weights[d]; + } + } + return agg; + } + + @Override + public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) { + final int dim1 = v1.getDimensionality(), dim2 = v2.getDimensionality(); + final int mindim = (dim1 < dim2) ? dim1 : dim2; + double agg = doublePreDistance(v1, v2, 0, mindim, 0.); + if (dim1 > mindim) { + agg = doublePreNorm(v1, mindim, dim1, agg); + } else if (dim2 > mindim) { + agg = doublePreNorm(v2, mindim, dim2, agg); + } + return agg; + } + + @Override + public double doubleNorm(NumberVector<?> v) { + return doublePreNorm(v, 0, v.getDimensionality(), 0.); + } + @Override public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) { - // Optimization for the simplest case - if (mbr1 instanceof NumberVector) { - if (mbr2 instanceof NumberVector) { - return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2); + final int dim1 = mbr1.getDimensionality(), dim2 = mbr2.getDimensionality(); + final int mindim = (dim1 < dim2) ? dim1 : dim2; + + final NumberVector<?> v1 = (mbr1 instanceof NumberVector) ? (NumberVector<?>) mbr1 : null; + final NumberVector<?> v2 = (mbr2 instanceof NumberVector) ? (NumberVector<?>) mbr2 : null; + + double agg = 0.; + if (v1 != null) { + if (v2 != null) { + agg = doublePreDistance(v1, v2, 0, mindim, agg); + } else { + agg = doublePreDistanceVM(v1, mbr2, 0, mindim, agg); + } + } else { + if (v2 != null) { + agg = doublePreDistanceVM(v2, mbr1, 0, mindim, agg); + } else { + agg = doublePreDistanceMBR(mbr1, mbr2, 0, mindim, agg); + } + } + // first object has more dimensions. + if (dim1 > mindim) { + if (v1 != null) { + agg = doublePreNorm(v1, mindim, dim1, agg); + } else { + agg = doublePreNormMBR(v1, mindim, dim1, agg); } } - // TODO: optimize for more simpler cases: obj vs. rect? - final int dim = dimensionality(mbr1, mbr2, weights.length); - double agg = 0; - for (int d = 0; d < dim; d++) { - final double diff; - if (mbr1.getMax(d) < mbr2.getMin(d)) { - diff = mbr2.getMin(d) - mbr1.getMax(d); - } else if (mbr1.getMin(d) > mbr2.getMax(d)) { - diff = mbr1.getMin(d) - mbr2.getMax(d); - } else { // The mbrs intersect! - continue; + // second object has more dimensions. + if (dim2 > mindim) { + if (v2 != null) { + agg = doublePreNorm(v2, mindim, dim2, agg); + } else { + agg = doublePreNormMBR(mbr2, mindim, dim2, agg); } - agg += diff * weights[d]; } return agg; } |