diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java | 163 |
1 files changed, 105 insertions, 58 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java index 48a9c5a2..ff2b15f3 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,13 +29,17 @@ import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedNumberVectorDistanceFunction; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleListParameter; /** - * Weighted version of the Minkowski L_p metrics distance function. + * Weighted version of the Minkowski L_p norm distance for {@link NumberVector}. * * @author Erich Schubert */ -public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { +public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction implements WeightedNumberVectorDistanceFunction<NumberVector> { /** * Weight array */ @@ -52,8 +56,8 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { this.weights = weights; } - private final double doublePreDistance(NumberVector<?> v1, NumberVector<?> v2, final int start, final int end, double agg) { - for (int d = start; d < end; d++) { + private final double preDistance(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 += Math.pow(delta, p) * weights[d]; @@ -61,35 +65,35 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { return agg; } - private final double doublePreDistanceVM(NumberVector<?> v, SpatialComparable mbr, final int start, final int end, double agg) { - for (int d = start; d < end; d++) { + private final double preDistanceVM(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.) { + if(delta < 0.) { delta = value - mbr.getMax(d); } - if (delta > 0.) { + if(delta > 0.) { agg += Math.pow(delta, p) * 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++) { + private final double preDistanceMBR(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.) { + if(delta < 0.) { delta = mbr1.getMin(d) - mbr2.getMax(d); } - if (delta > 0.) { + if(delta > 0.) { agg += Math.pow(delta, p) * 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++) { + private final double preNorm(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 += Math.pow(delta, p) * weights[d]; @@ -97,13 +101,13 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { return agg; } - private final double doublePreNormMBR(SpatialComparable mbr, final int start, final int end, double agg) { - for (int d = start; d < end; d++) { + private final double preNormMBR(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.) { + if(delta < 0.) { delta = -mbr.getMax(d); } - if (delta > 0.) { + if(delta > 0.) { agg += Math.pow(delta, p) * weights[d]; } } @@ -111,59 +115,65 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { } @Override - public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) { + public double distance(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); + double agg = preDistance(v1, v2, 0, mindim, 0.); + if(dim1 > mindim) { + agg = preNorm(v1, mindim, dim1, agg); + } + else if(dim2 > mindim) { + agg = preNorm(v2, mindim, dim2, agg); } return Math.pow(agg, invp); } @Override - public double doubleNorm(NumberVector<?> v) { - return Math.pow(doublePreNorm(v, 0, v.getDimensionality(), 0.), invp); + public double norm(NumberVector v) { + return Math.pow(preNorm(v, 0, v.getDimensionality(), 0.), invp); } @Override - public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) { + public double minDist(SpatialComparable mbr1, SpatialComparable 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; + 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); + if(v1 != null) { + if(v2 != null) { + agg = preDistance(v1, v2, 0, mindim, agg); } - } else { - if (v2 != null) { - agg = doublePreDistanceVM(v2, mbr1, 0, mindim, agg); - } else { - agg = doublePreDistanceMBR(mbr1, mbr2, 0, mindim, agg); + else { + agg = preDistanceVM(v1, mbr2, 0, mindim, agg); + } + } + else { + if(v2 != null) { + agg = preDistanceVM(v2, mbr1, 0, mindim, agg); + } + else { + agg = preDistanceMBR(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); + if(dim1 > mindim) { + if(v1 != null) { + agg = preNorm(v1, mindim, dim1, agg); + } + else { + agg = preNormMBR(v1, mindim, dim1, agg); } } // second object has more dimensions. - if (dim2 > mindim) { - if (v2 != null) { - agg = doublePreNorm(v2, mindim, dim2, agg); - } else { - agg = doublePreNormMBR(mbr2, mindim, dim2, agg); + if(dim2 > mindim) { + if(v2 != null) { + agg = preNorm(v2, mindim, dim2, agg); + } + else { + agg = preNormMBR(mbr2, mindim, dim2, agg); } } return Math.pow(agg, invp); @@ -171,16 +181,16 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { @Override public boolean equals(Object obj) { - if (this == obj) { + if(this == obj) { return true; } - if (obj == null) { + if(obj == null) { return false; } - if (!(obj instanceof WeightedLPNormDistanceFunction)) { - if (obj instanceof LPNormDistanceFunction && super.equals(obj)) { - for (double d : weights) { - if (d != 1.) { + if(!(obj instanceof WeightedLPNormDistanceFunction)) { + if(obj instanceof LPNormDistanceFunction && super.equals(obj)) { + for(double d : weights) { + if(d != 1.) { return false; } } @@ -193,7 +203,44 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction { } @Override - public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() { - return new VectorFieldTypeInformation<>(NumberVector.class, 0, weights.length); + public SimpleTypeInformation<? super NumberVector> getInputTypeRestriction() { + return VectorFieldTypeInformation.typeRequest(NumberVector.class, 0, weights.length); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends LPNormDistanceFunction.Parameterizer { + /** + * Weight array + */ + protected double[] weights; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + DoubleListParameter weightsP = new DoubleListParameter(WEIGHTS_ID); + if(config.grab(weightsP)) { + weights = ArrayLikeUtil.toPrimitiveDoubleArray(weightsP.getValue()); + } + } + + @Override + protected WeightedLPNormDistanceFunction makeInstance() { + if(p == 1.) { + return new WeightedManhattanDistanceFunction(weights); + } + if(p == 2.) { + return new WeightedEuclideanDistanceFunction(weights); + } + if(p == Double.POSITIVE_INFINITY) { + return new WeightedMaximumDistanceFunction(weights); + } + return new WeightedLPNormDistanceFunction(p, weights); + } } } |