summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java
diff options
context:
space:
mode:
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.java128
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;
}